Compare commits
No commits in common. "bc6ae2bea8738102009cb875c2bfdef0f6bff1bf" and "e0391bc8613439c552467d94a15f9e49c0d1c8ea" have entirely different histories.
bc6ae2bea8
...
e0391bc861
27
README.md
27
README.md
|
@ -1,5 +1,24 @@
|
||||||
# self-hosting
|
<!---
|
||||||
|
|
||||||
|
Copyright (C) 2020 Jef Roosens
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
# self-hosting
|
||||||
# Contents
|
# Contents
|
||||||
The repo contains setup guides for the following:
|
The repo contains setup guides for the following:
|
||||||
|
|
||||||
|
@ -16,11 +35,9 @@ Each directory contains (or will contain) its own `README.md` to aid with the
|
||||||
installation of that specific setup.
|
installation of that specific setup.
|
||||||
|
|
||||||
# General info
|
# General info
|
||||||
|
|
||||||
This info applies to all configs.
|
This info applies to all configs.
|
||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
All the setups named above use Docker and docker-compose. If you're on a
|
All the setups named above use Docker and docker-compose. If you're on a
|
||||||
Linux-based server, you can find both `docker` and `docker-compose` in your
|
Linux-based server, you can find both `docker` and `docker-compose` in your
|
||||||
package manager (do note that the Docker package might be called `docker.io`).
|
package manager (do note that the Docker package might be called `docker.io`).
|
||||||
|
@ -28,27 +45,23 @@ Otherwise, the install instructions can be found
|
||||||
[here](https://docs.docker.com/engine/install/).
|
[here](https://docs.docker.com/engine/install/).
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Most configuration can be done using a `.env` file with a provided
|
Most configuration can be done using a `.env` file with a provided
|
||||||
`.env.example` file to start from. This means that you never have to edit the
|
`.env.example` file to start from. This means that you never have to edit the
|
||||||
compose files, unless you wish to deviate from the default format.
|
compose files, unless you wish to deviate from the default format.
|
||||||
|
|
||||||
## Building the image
|
## Building the image
|
||||||
|
|
||||||
You can build the container image using the command `docker-compose build`.
|
You can build the container image using the command `docker-compose build`.
|
||||||
This will build all services specified in the `docker-compose.yml` file. Any
|
This will build all services specified in the `docker-compose.yml` file. Any
|
||||||
build configuration/environment variables can be defined in a `.env` file. A
|
build configuration/environment variables can be defined in a `.env` file. A
|
||||||
`.env.example` file is given for each configuration.
|
`.env.example` file is given for each configuration.
|
||||||
|
|
||||||
## Running the container
|
## Running the container
|
||||||
|
|
||||||
For running the server, we can use `docker-compose up -d`. This will start the
|
For running the server, we can use `docker-compose up -d`. This will start the
|
||||||
service in the background. You can then see any logs using
|
service in the background. You can then see any logs using
|
||||||
`docker-compose logs`. If you want the logs to update automatically, use
|
`docker-compose logs`. If you want the logs to update automatically, use
|
||||||
`docker-compose logs -f`.
|
`docker-compose logs -f`.
|
||||||
|
|
||||||
# Why did I make this?
|
# Why did I make this?
|
||||||
|
|
||||||
Well, I just wanted to put all my knowledge in one basket. this makes it easier
|
Well, I just wanted to put all my knowledge in one basket. this makes it easier
|
||||||
to manage and share with others. I spend a lot of time tweaking these configs
|
to manage and share with others. I spend a lot of time tweaking these configs
|
||||||
and figuring out how they work best (for me at least), and wanted to share this
|
and figuring out how they work best (for me at least), and wanted to share this
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
__pycache__/
|
||||||
|
backup_tool
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Backups
|
||||||
|
I wrote this Python program to manage backups of the stuff running on our
|
||||||
|
server. I know there's probably better ways to do this, but I really liked
|
||||||
|
working on this and it works well enough for our usecase.
|
|
@ -0,0 +1,41 @@
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
from specs import parse_specs_file
|
||||||
|
|
||||||
|
|
||||||
|
# This just displays the error type and message, not the stack trace
|
||||||
|
def except_hook(ext_type, value, traceback):
|
||||||
|
sys.stderr.write("{}: {}\n".format(ext_type.__name__, value))
|
||||||
|
|
||||||
|
sys.excepthook = except_hook
|
||||||
|
|
||||||
|
|
||||||
|
# Define parser
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description='Backup directories and Docker volumes.')
|
||||||
|
parser.add_argument('-f', '--file', action='append', dest='file',
|
||||||
|
help='File containing spec definitions.')
|
||||||
|
parser.add_argument('-j', '--json', action='store_const', const=True,
|
||||||
|
default=False, help='Print out the parsed specs as JSON '
|
||||||
|
'and exit')
|
||||||
|
parser.add_argument('spec', nargs='*',
|
||||||
|
help='The specs to process. Defaults to all.')
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
args = parser.parse_args()
|
||||||
|
specs = sum([parse_specs_file(path) for path in args.file], [])
|
||||||
|
|
||||||
|
# Filter specs if needed
|
||||||
|
if args.spec:
|
||||||
|
specs = filter(lambda s: s.name in args.spec, specs)
|
||||||
|
|
||||||
|
# Dump parsed data as json
|
||||||
|
if args.json:
|
||||||
|
import json
|
||||||
|
print(json.dumps([spec.to_dict() for spec in specs], indent=4))
|
||||||
|
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
# Run the backups
|
||||||
|
# for spec in specs:
|
||||||
|
# spec.backup()
|
|
@ -0,0 +1,2 @@
|
||||||
|
from .specs import Spec
|
||||||
|
from .parser import parse_specs_file
|
|
@ -0,0 +1,114 @@
|
||||||
|
import yaml
|
||||||
|
from pathlib import Path
|
||||||
|
from specs import Spec
|
||||||
|
from typing import List, Dict
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidKeyError(Exception):
|
||||||
|
def __init__(self, key):
|
||||||
|
message = "Invalid key: {}".format(key)
|
||||||
|
|
||||||
|
super().__init__(key)
|
||||||
|
|
||||||
|
|
||||||
|
class MissingKeyError(Exception):
|
||||||
|
def __init__(self, key):
|
||||||
|
message = "Missing key: {}".format(key)
|
||||||
|
|
||||||
|
super().__init__(key)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_specs_file(path: Path) -> List[Spec]:
|
||||||
|
"""
|
||||||
|
Parse a YAML file defining backup specs.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path: path to the specs file
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list of specs
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Skeleton of a spec config
|
||||||
|
# If a value is None, this means it doesn't have a default value and must be
|
||||||
|
# defined
|
||||||
|
spec_skel = {
|
||||||
|
"source": None,
|
||||||
|
"destination": None,
|
||||||
|
"limit": None,
|
||||||
|
"volume": False,
|
||||||
|
"notify": {
|
||||||
|
"title": "Backup Notification",
|
||||||
|
"events": ["failure"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read YAML file
|
||||||
|
with open(path, "r") as yaml_file:
|
||||||
|
data = yaml.load(yaml_file, Loader=yaml.Loader)
|
||||||
|
|
||||||
|
# Check specs section exists
|
||||||
|
if "specs" not in data:
|
||||||
|
raise MissingKeyError("specs")
|
||||||
|
|
||||||
|
# Allow for default notify settings
|
||||||
|
if "notify" in data:
|
||||||
|
spec_skel["notify"] = data["notify"]
|
||||||
|
|
||||||
|
specs = []
|
||||||
|
# Check format for each spec
|
||||||
|
for key in data["specs"]:
|
||||||
|
specs.append(Spec.from_dict(key, combine_with_skeleton(
|
||||||
|
data["specs"][key], spec_skel)
|
||||||
|
))
|
||||||
|
|
||||||
|
return specs
|
||||||
|
|
||||||
|
|
||||||
|
def combine_with_skeleton(data: Dict, skel: Dict) -> Dict:
|
||||||
|
"""
|
||||||
|
Compare a dict with a given skeleton dict, and fill in default values where
|
||||||
|
needed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# First, check for illegal keys
|
||||||
|
for key in data:
|
||||||
|
if key not in skel:
|
||||||
|
raise InvalidKeyError(key)
|
||||||
|
|
||||||
|
# Then, check the default values
|
||||||
|
for key, value in skel.items():
|
||||||
|
if key not in data:
|
||||||
|
# Raise error if there's not default value
|
||||||
|
if value is None:
|
||||||
|
raise MissingKeyError(key)
|
||||||
|
|
||||||
|
# Replace with default value
|
||||||
|
data[key] = value
|
||||||
|
|
||||||
|
# Error if value is not same type as default value
|
||||||
|
elif type(data[key]) != type(value) and value is not None:
|
||||||
|
raise TypeError("Invalid value type")
|
||||||
|
|
||||||
|
# Recurse into dicts
|
||||||
|
elif type(value) == dict:
|
||||||
|
data[key] = combine_with_skeleton(data[key], value)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
# Test cases
|
||||||
|
if __name__ == "__main__":
|
||||||
|
d1 = {
|
||||||
|
"a": 5
|
||||||
|
}
|
||||||
|
s1 = {
|
||||||
|
"a": 7,
|
||||||
|
"b": 2
|
||||||
|
}
|
||||||
|
r1 = {
|
||||||
|
"a": 5,
|
||||||
|
"b": 2
|
||||||
|
}
|
||||||
|
|
||||||
|
assert combine_with_skeleton(d1, s1) == r1
|
|
@ -0,0 +1,146 @@
|
||||||
|
from pathlib import Path
|
||||||
|
from datetime import datetime
|
||||||
|
import requests
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class Spec:
|
||||||
|
def __init__(self, name, destination, limit, title, events=None):
|
||||||
|
self.name = name
|
||||||
|
self.destination = Path(destination)
|
||||||
|
self.limit = limit
|
||||||
|
self.title = title
|
||||||
|
self.events = [] if events is None else events
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return {
|
||||||
|
"name": self.name,
|
||||||
|
"destination": str(self.destination),
|
||||||
|
"limit": self.limit,
|
||||||
|
"notify": {
|
||||||
|
"title": self.title,
|
||||||
|
"events": self.events
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def backup(self):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def remove_redundant(self):
|
||||||
|
tarballs = sorted(self.destination.glob('*.tar.gz'),
|
||||||
|
key=os.path.getmtime, reverse=True)
|
||||||
|
|
||||||
|
if len(tarballs) >= self.limit:
|
||||||
|
for path in tarballs[self.limit - 1:]:
|
||||||
|
path.unlink()
|
||||||
|
|
||||||
|
def notify(self, status_code):
|
||||||
|
if status_code:
|
||||||
|
if "failure" not in self.events:
|
||||||
|
return
|
||||||
|
|
||||||
|
message = "backup for {} failed.".format(self.name)
|
||||||
|
|
||||||
|
else:
|
||||||
|
if "success" not in self.events:
|
||||||
|
return
|
||||||
|
|
||||||
|
message = "backup for {} succeeded.".format(self.name)
|
||||||
|
|
||||||
|
# Read API key from env vars
|
||||||
|
try:
|
||||||
|
key = os.environ["IFTTT_API_KEY"]
|
||||||
|
|
||||||
|
# Don't send notification if there's not API key defined
|
||||||
|
except KeyError:
|
||||||
|
return
|
||||||
|
|
||||||
|
url = "https://maker.ifttt.com/trigger/{}/with/key/{}".format(
|
||||||
|
"phone_notifications",
|
||||||
|
key
|
||||||
|
)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"value1": self.title,
|
||||||
|
"value2": message
|
||||||
|
}
|
||||||
|
|
||||||
|
requests.post(url, data=data)
|
||||||
|
|
||||||
|
def get_filename(self):
|
||||||
|
return '{}_{}.tar.gz'.format(
|
||||||
|
self.name,
|
||||||
|
datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_dict(name, data) -> "Specification":
|
||||||
|
if data.get("volume", False):
|
||||||
|
return VolumeSpec.from_dict(name, data)
|
||||||
|
|
||||||
|
return DirSpec.from_dict(name, data)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_file(path: str):
|
||||||
|
with open(path, 'r') as yaml_file:
|
||||||
|
data = yaml.load(yaml_file, Loader=yaml.Loader)
|
||||||
|
|
||||||
|
return [Spec.from_dict(name, info)
|
||||||
|
for name, info in data["specs"].items()]
|
||||||
|
|
||||||
|
|
||||||
|
class DirSpec(Spec):
|
||||||
|
def __init__(self, name, source, destination, limit, title, events=None):
|
||||||
|
super().__init__(name, destination, limit, title, events)
|
||||||
|
|
||||||
|
self.source = Path(source)
|
||||||
|
|
||||||
|
def backup(self):
|
||||||
|
self.remove_redundant()
|
||||||
|
|
||||||
|
status_code = os.system(
|
||||||
|
"tar -C '{}' -czf '{}' -- .".format(
|
||||||
|
self.source,
|
||||||
|
self.destination / self.get_filename()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.notify(status_code)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_dict(name, data):
|
||||||
|
return DirSpec(
|
||||||
|
name,
|
||||||
|
data["source"],
|
||||||
|
data["destination"],
|
||||||
|
data["limit"],
|
||||||
|
data["notify"]["title"],
|
||||||
|
data["notify"]["events"]
|
||||||
|
)
|
||||||
|
|
||||||
|
class VolumeSpec(Spec):
|
||||||
|
def __init__(self, name, volume, destination, limit, title, events=None):
|
||||||
|
super().__init__(name, destination, limit, title, events)
|
||||||
|
|
||||||
|
self.volume = volume
|
||||||
|
|
||||||
|
def backup(self):
|
||||||
|
status_code = os.system(
|
||||||
|
"docker run --rm -v '{}:/from' -v '{}:/to' alpine:latest "
|
||||||
|
"tar -C /from -czf '/to/{}' -- .".format(
|
||||||
|
self.volume,
|
||||||
|
self.destination,
|
||||||
|
self.get_filename()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_dict(name, data):
|
||||||
|
return VolumeSpec(
|
||||||
|
name,
|
||||||
|
data["source"],
|
||||||
|
data["destination"],
|
||||||
|
data["limit"],
|
||||||
|
data["notify"]["title"],
|
||||||
|
data["notify"]["events"]
|
||||||
|
)
|
|
@ -0,0 +1,15 @@
|
||||||
|
notify:
|
||||||
|
title: "title"
|
||||||
|
events:
|
||||||
|
- 'random'
|
||||||
|
|
||||||
|
specs:
|
||||||
|
test-spec:
|
||||||
|
source: '/some/path'
|
||||||
|
destination: '/some/other/path'
|
||||||
|
limit: 7
|
||||||
|
|
||||||
|
test-2:
|
||||||
|
source: '/path/to'
|
||||||
|
destination: '/to/some/other/path'
|
||||||
|
limit: 2
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# Zip app
|
||||||
|
(cd app && zip -r ../app.zip * -x "__pycache__/*" "**/__pycache__/*" ".vim/*" "**/.vim/*")
|
||||||
|
|
||||||
|
# Add shebang to top of file
|
||||||
|
echo "#!/usr/bin/env python3" | cat - app.zip > backup_tool
|
||||||
|
chmod a+x backup_tool
|
||||||
|
|
||||||
|
# Move executable over
|
||||||
|
mv backup_tool /usr/local/bin
|
||||||
|
|
||||||
|
# Remove zip
|
||||||
|
rm app.zip
|
|
@ -63,7 +63,7 @@ DB_HOST=db
|
||||||
DB_PORT=5432
|
DB_PORT=5432
|
||||||
DB_DATABASE=firefly
|
DB_DATABASE=firefly
|
||||||
DB_USERNAME=firefly
|
DB_USERNAME=firefly
|
||||||
DB_PASSWORD=firefly
|
DB_PASSWORD=password
|
||||||
|
|
||||||
# MySQL supports SSL. You can configure it here.
|
# MySQL supports SSL. You can configure it here.
|
||||||
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
|
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
version: '2.4'
|
version: '2.8'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
|
@ -6,23 +6,24 @@ services:
|
||||||
context: '.'
|
context: '.'
|
||||||
args:
|
args:
|
||||||
- 'LOCALE=$DEFAULT_LOCALE'
|
- 'LOCALE=$DEFAULT_LOCALE'
|
||||||
image: 'chewingbever/firefly-iii-cron:latest'
|
image: 'firefly-iii-cron:latest'
|
||||||
restart: 'always'
|
restart: 'always'
|
||||||
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: 'curl -f localhost:8080 || exit 1'
|
test: 'curl -f localhost:8080 || exit 1'
|
||||||
interval: '1m'
|
interval: '1m'
|
||||||
timeout: '10s'
|
timeout: '10s'
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: '10s'
|
start_period: '10s'
|
||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
condition: 'service_healthy'
|
condition: 'service_healthy'
|
||||||
redis:
|
redis:
|
||||||
condition: 'service_healthy'
|
condition: 'service_healthy'
|
||||||
|
|
||||||
env_file:
|
env_file:
|
||||||
- '.env'
|
- '.env'
|
||||||
|
labels:
|
||||||
|
- 'com.centurylinklabs.watchtower.enable=true'
|
||||||
networks:
|
networks:
|
||||||
- 'nginx'
|
- 'nginx'
|
||||||
- 'default'
|
- 'default'
|
||||||
|
@ -30,33 +31,35 @@ services:
|
||||||
- 'upload:/var/www/html/storage/upload'
|
- 'upload:/var/www/html/storage/upload'
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: 'postgres:13.2-alpine'
|
image: 'postgres:13-alpine'
|
||||||
restart: 'always'
|
restart: 'always'
|
||||||
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: 'pg_isready -U firefly'
|
test: 'pg_isready -U $DB_USERNAME'
|
||||||
interval: '10s'
|
interval: '10s'
|
||||||
timeout: '5s'
|
timeout: '5s'
|
||||||
retries: 5
|
retries: 5
|
||||||
start_period: '0s'
|
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
- 'POSTGRES_DB=firefly'
|
- 'POSTGRES_DB=$DB_DATABASE'
|
||||||
- 'POSTGRES_PASSWORD=firefly'
|
- 'POSTGRES_PASSWORD=$DB_PASSWORD'
|
||||||
- 'POSTGRES_USER=firefly'
|
- 'POSTGRES_USER=$DB_USERNAME'
|
||||||
|
labels:
|
||||||
|
- 'com.centurylinklabs.watchtower.enable=true'
|
||||||
volumes:
|
volumes:
|
||||||
- 'db-data:/var/lib/postgresql/data'
|
- 'db-data:/var/lib/postgresql/data'
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: 'redis:6.2.2-alpine'
|
image: 'redis:6-alpine'
|
||||||
restart: 'always'
|
restart: 'always'
|
||||||
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: 'redis-cli -h localhost ping'
|
test: 'redis-cli -h localhost ping'
|
||||||
interval: '10s'
|
interval: '10s'
|
||||||
timeout: '5s'
|
timeout: '5s'
|
||||||
retries: 3
|
retries: 3
|
||||||
|
|
||||||
|
labels:
|
||||||
|
- 'com.centurylinklabs.watchtower.enable=true'
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
nginx:
|
nginx:
|
||||||
external: true
|
external: true
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
# User to run container as
|
|
||||||
USER_UID=1000
|
|
||||||
USER_GID=1000
|
|
||||||
|
|
||||||
# Database settings
|
|
||||||
DB_TYPE=postgres
|
|
||||||
DB_HOST=db:5432
|
|
||||||
DB_NAME=gitea
|
|
||||||
DB_USER=gitea
|
|
||||||
DB_PASSWD=gitea
|
|
||||||
|
|
||||||
# Wether to start LFS
|
|
||||||
LFS_START_SERVER=true
|
|
||||||
|
|
||||||
# Wether to allow registration
|
|
||||||
DISABLE_REGISTRATION=true
|
|
|
@ -1,59 +0,0 @@
|
||||||
version: '2.4'
|
|
||||||
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
# Latest contains a development version
|
|
||||||
image: 'gitea/gitea:1.14.1-rootless'
|
|
||||||
restart: 'always'
|
|
||||||
|
|
||||||
depends_on:
|
|
||||||
db:
|
|
||||||
condition: 'service_healthy'
|
|
||||||
healthcheck:
|
|
||||||
test: 'curl -f localhost:3000 || exit 1'
|
|
||||||
interval: '30s'
|
|
||||||
timeout: '5s'
|
|
||||||
retries: 3
|
|
||||||
start_period: '5s'
|
|
||||||
|
|
||||||
env_file:
|
|
||||||
- '.env'
|
|
||||||
networks:
|
|
||||||
- 'default'
|
|
||||||
- 'nginx'
|
|
||||||
ports:
|
|
||||||
- '22:22'
|
|
||||||
volumes:
|
|
||||||
- 'data:/data'
|
|
||||||
- 'repos:/data/git/repositories'
|
|
||||||
- 'lfs:/data/git/lfs'
|
|
||||||
- '/etc/timezone:/etc/timezone:ro'
|
|
||||||
- '/etc/localtime:/etc/localtime:ro'
|
|
||||||
|
|
||||||
db:
|
|
||||||
image: 'postgres:13.2-alpine'
|
|
||||||
restart: 'always'
|
|
||||||
|
|
||||||
healthcheck:
|
|
||||||
test: 'pg_isready -U gitea'
|
|
||||||
interval: '30s'
|
|
||||||
timeout: '5s'
|
|
||||||
retries: 3
|
|
||||||
start_period: '0s'
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- 'POSTGRES_USER=gitea'
|
|
||||||
- 'POSTGRES_PASSWORD=gitea'
|
|
||||||
- 'POSTGRES_DB=gitea'
|
|
||||||
volumes:
|
|
||||||
- 'db-data:/var/lib/postgresql/data'
|
|
||||||
|
|
||||||
networks:
|
|
||||||
nginx:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
data:
|
|
||||||
lfs:
|
|
||||||
db-data:
|
|
||||||
repos:
|
|
|
@ -12,7 +12,7 @@ DB_HOST=db
|
||||||
DB_PORT=3306
|
DB_PORT=3306
|
||||||
DB_DATABASE=koel
|
DB_DATABASE=koel
|
||||||
DB_USERNAME=koel
|
DB_USERNAME=koel
|
||||||
DB_PASSWORD=koel
|
DB_PASSWORD=changeme
|
||||||
|
|
||||||
# A random 32-char string. You can leave this empty if use php artisan koel:init.
|
# A random 32-char string. You can leave this empty if use php artisan koel:init.
|
||||||
APP_KEY=
|
APP_KEY=
|
||||||
|
|
|
@ -1,22 +1,14 @@
|
||||||
version: '2.4'
|
version: '3.5'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
# This repository sadly only has a 'latest' flag
|
|
||||||
image: 'hyzual/koel:latest'
|
image: 'hyzual/koel:latest'
|
||||||
restart: 'always'
|
restart: 'always'
|
||||||
|
|
||||||
healthcheck:
|
|
||||||
test: 'curl -f localhost:80 || exit 1'
|
|
||||||
interval: '1m'
|
|
||||||
timeout: '10s'
|
|
||||||
retries: 3
|
|
||||||
start_period: '10s'
|
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
- 'db'
|
||||||
# Haven't found a good MySQL healthcheck yet
|
labels:
|
||||||
condition: 'service_started'
|
- 'com.centurylinklabs.watchtower.enable=true'
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
- 'default'
|
- 'default'
|
||||||
- 'nginx'
|
- 'nginx'
|
||||||
|
@ -24,18 +16,19 @@ services:
|
||||||
- './.env:/var/www/html/.env'
|
- './.env:/var/www/html/.env'
|
||||||
- 'covers:/var/www/html/public/img/covers'
|
- 'covers:/var/www/html/public/img/covers'
|
||||||
- 'music:/music'
|
- 'music:/music'
|
||||||
- 'index:/var/www/html/storage/search-indexes'
|
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: 'mariadb:10.5.9-focal'
|
image: 'mysql:8'
|
||||||
restart: 'always'
|
restart: 'always'
|
||||||
command: '--default-authentication-plugin=mysql_native_password'
|
command: '--default-authentication-plugin=mysql_native_password'
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
- 'MYSQL_DATABASE=koel'
|
- 'MYSQL_DATABASE=koel'
|
||||||
- 'MYSQL_USER=koel'
|
- 'MYSQL_PASSWORD=$DB_PASSWORD'
|
||||||
- 'MYSQL_PASSWORD=koel'
|
- 'MYSQL_ROOT_PASSWORD=$DB_PASSWORD'
|
||||||
- 'MYSQL_RANDOM_ROOT_PASSWORD=yes'
|
- 'MYSQL_USER=$DB_USERNAME'
|
||||||
|
labels:
|
||||||
|
- 'com.centurylinklabs.watchtower.enable=true'
|
||||||
volumes:
|
volumes:
|
||||||
- 'db-data:/var/lib/mysql'
|
- 'db-data:/var/lib/mysql'
|
||||||
|
|
||||||
|
@ -46,5 +39,4 @@ networks:
|
||||||
volumes:
|
volumes:
|
||||||
covers:
|
covers:
|
||||||
db-data:
|
db-data:
|
||||||
index:
|
|
||||||
music:
|
music:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
version: '2.0'
|
version: '3.5'
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
build:
|
build:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
version: '2.0'
|
version: '3.5'
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
build:
|
build:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
version: '2.0'
|
version: '3.5'
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
build:
|
build:
|
||||||
|
@ -7,7 +7,7 @@ services:
|
||||||
- 'BASE_IMAGE'
|
- 'BASE_IMAGE'
|
||||||
- 'MC_VERSION'
|
- 'MC_VERSION'
|
||||||
- 'PAPERMC_VERSION'
|
- 'PAPERMC_VERSION'
|
||||||
image: 'localhost:5000/mc-papermc:${MC_VERSION}-${PAPERMC_VERSION}'
|
image: 'chewingbever/mc-papermc:${MC_VERSION}-${PAPERMC_VERSION}'
|
||||||
restart: 'always'
|
restart: 'always'
|
||||||
|
|
||||||
# Needed to interact with server console
|
# Needed to interact with server console
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
POSTGRES_DB=miniflux
|
||||||
|
POSTGRES_USER=miniflux
|
||||||
|
POSTGRES_PASSWORD=changeme
|
|
@ -1,44 +1,28 @@
|
||||||
version: '2.4'
|
version: '3.5'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
image: 'miniflux/miniflux:2.0.29'
|
image: 'miniflux/miniflux:latest'
|
||||||
restart: 'always'
|
restart: 'always'
|
||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
- 'db'
|
||||||
condition: 'service_healthy'
|
|
||||||
healthcheck:
|
|
||||||
test: 'wget --no-verbose --tries=1 --spider http://localhost:8080/ || exit 1'
|
|
||||||
interval: '1m'
|
|
||||||
timeout: '5s'
|
|
||||||
retries: 3
|
|
||||||
start_period: '5s'
|
|
||||||
|
|
||||||
env_file:
|
env_file:
|
||||||
- '.env'
|
- 'miniflux.env'
|
||||||
environment:
|
labels:
|
||||||
# This is always the same, so we just put it here
|
- 'com.centurylinklabs.watchtower.enable=true'
|
||||||
- 'DATABASE_URL=postgres://miniflux:miniflux@db/miniflux?sslmode=disable'
|
|
||||||
networks:
|
networks:
|
||||||
- 'default'
|
- 'default'
|
||||||
- 'nginx'
|
- 'nginx'
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: 'postgres:13.2-alpine'
|
image: 'postgres:13-alpine'
|
||||||
restart: 'always'
|
restart: 'always'
|
||||||
|
|
||||||
healthcheck:
|
env_file:
|
||||||
test: 'pg_isready -U miniflux'
|
- 'db.env'
|
||||||
interval: '10s'
|
labels:
|
||||||
timeout: '5s'
|
- 'com.centurylinklabs.watchtower.enable=true'
|
||||||
retries: 5
|
|
||||||
start_period: '0s'
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- 'POSTGRES_DB=miniflux'
|
|
||||||
- 'POSTGRES_USER=miniflux'
|
|
||||||
- 'POSTGRES_PASSWORD=miniflux'
|
|
||||||
volumes:
|
volumes:
|
||||||
- 'db-data:/var/lib/postgresql/data'
|
- 'db-data:/var/lib/postgresql/data'
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Database settings
|
# Database settings
|
||||||
|
DATABASE_URL=postgres://miniflux:changeme@db/miniflux?sslmode=disable
|
||||||
RUN_MIGRATIONS=1
|
RUN_MIGRATIONS=1
|
||||||
|
|
||||||
# Auto-create admin user
|
# Auto-create admin user
|
|
@ -1,168 +0,0 @@
|
||||||
#
|
|
||||||
# Welcome, friend ❤. Thanks for trying out Monica. We hope you'll have fun.
|
|
||||||
#
|
|
||||||
|
|
||||||
# Two choices: local|production. Use local if you want to install Monica as a
|
|
||||||
# development version. Use production otherwise.
|
|
||||||
APP_ENV=production
|
|
||||||
|
|
||||||
# true if you want to show debug information on errors. For production, put this
|
|
||||||
# to false.
|
|
||||||
APP_DEBUG=false
|
|
||||||
|
|
||||||
# The encryption key. This is the most important part of the application. Keep
|
|
||||||
# this secure otherwise, everyone will be able to access your application.
|
|
||||||
# Must be 32 characters long exactly.
|
|
||||||
# Use `php artisan key:generate` or `pwgen -s 32 1` to generate a random key.
|
|
||||||
APP_KEY=ChangeMeBy32KeyLengthOrGenerated
|
|
||||||
|
|
||||||
# Prevent information leakage by referring to IDs with hashIds instead of
|
|
||||||
# the actual IDs used in the database.
|
|
||||||
HASH_SALT=ChangeMeBy20+KeyLength
|
|
||||||
HASH_LENGTH=18
|
|
||||||
|
|
||||||
# The URL of your application.
|
|
||||||
APP_URL=http://localhost
|
|
||||||
|
|
||||||
# Force using APP_URL as base url of your application.
|
|
||||||
# You should not need this, unless you are using subdirectory config.
|
|
||||||
APP_FORCE_URL=false
|
|
||||||
|
|
||||||
# Database information
|
|
||||||
# To keep this information secure, we urge you to change the default password
|
|
||||||
# Currently only "mysql" compatible servers are working
|
|
||||||
DB_CONNECTION=mysql
|
|
||||||
DB_HOST=db
|
|
||||||
DB_PORT=3306
|
|
||||||
# You can use mysql unix socket if available, it overrides DB_HOST and DB_PORT values.
|
|
||||||
#DB_UNIX_SOCKET=/var/run/mysqld/mysqld.sock
|
|
||||||
DB_DATABASE=monica
|
|
||||||
DB_USERNAME=monica
|
|
||||||
DB_PASSWORD=monica
|
|
||||||
DB_PREFIX=
|
|
||||||
DB_TEST_HOST=127.0.0.1
|
|
||||||
DB_TEST_DATABASE=monica_test
|
|
||||||
DB_TEST_USERNAME=homestead
|
|
||||||
DB_TEST_PASSWORD=secret
|
|
||||||
|
|
||||||
# Use utf8mb4 database charset format to support emoji characters
|
|
||||||
# ⚠ be sure your DBMS supports utf8mb4 format
|
|
||||||
DB_USE_UTF8MB4=true
|
|
||||||
|
|
||||||
# Mail credentials used to send emails from the application.
|
|
||||||
MAIL_MAILER=smtp
|
|
||||||
MAIL_HOST=mailtrap.io
|
|
||||||
MAIL_PORT=2525
|
|
||||||
MAIL_USERNAME=
|
|
||||||
MAIL_PASSWORD=
|
|
||||||
MAIL_ENCRYPTION=
|
|
||||||
# Outgoing emails will be sent with these identity
|
|
||||||
MAIL_FROM_ADDRESS=
|
|
||||||
MAIL_FROM_NAME="Monica instance"
|
|
||||||
# New registration notification sent to this email
|
|
||||||
APP_EMAIL_NEW_USERS_NOTIFICATION=
|
|
||||||
|
|
||||||
# Ability to disable signups on your instance.
|
|
||||||
# Can be true or false. Default to false.
|
|
||||||
APP_DISABLE_SIGNUP=true
|
|
||||||
|
|
||||||
# Enable user email verification.
|
|
||||||
APP_SIGNUP_DOUBLE_OPTIN=false
|
|
||||||
|
|
||||||
# Set trusted proxy IP addresses.
|
|
||||||
# To trust all proxies that connect directly to your server, use a "*".
|
|
||||||
# To trust one or more specific proxies that connect directly to your server,
|
|
||||||
# use a comma separated list of IP addresses.
|
|
||||||
APP_TRUSTED_PROXIES=*
|
|
||||||
|
|
||||||
# Enable automatic cloudflare trusted proxy discover
|
|
||||||
APP_TRUSTED_CLOUDFLARE=false
|
|
||||||
|
|
||||||
# Frequency of creation of new log files. Logs are written when an error occurs.
|
|
||||||
# Refer to config/logging.php for the possible values.
|
|
||||||
LOG_CHANNEL=daily
|
|
||||||
|
|
||||||
# Error tracking. Specific to hosted version on .com. You probably don't need
|
|
||||||
# those.
|
|
||||||
SENTRY_SUPPORT=false
|
|
||||||
SENTRY_LARAVEL_DSN=
|
|
||||||
|
|
||||||
# Send a daily ping to https://version.monicahq.com to check if a new version
|
|
||||||
# is available. When a new version is detected, you will have a message in the
|
|
||||||
# UI, as well as the release notes for the new changes. Can be true or false.
|
|
||||||
# Default to true.
|
|
||||||
CHECK_VERSION=true
|
|
||||||
|
|
||||||
# Cache, session, and queue parameters
|
|
||||||
# ⚠ Change this only if you know what you are doing
|
|
||||||
#. Cache: database, file, memcached, redis, dynamodb
|
|
||||||
#. Session: file, cookie, database, apc, memcached, redis, array
|
|
||||||
#. Queue: sync, database, beanstalkd, sqs, redis
|
|
||||||
# If Queue is not set to 'sync', you'll have to set a queue worker
|
|
||||||
# See https://laravel.com/docs/5.7/queues#running-the-queue-worker
|
|
||||||
CACHE_DRIVER=redis
|
|
||||||
SESSION_DRIVER=file
|
|
||||||
SESSION_LIFETIME=120
|
|
||||||
QUEUE_CONNECTION=sync
|
|
||||||
|
|
||||||
# If you use redis, set the redis host or ip, like:
|
|
||||||
REDIS_HOST=redis
|
|
||||||
|
|
||||||
# Maximum allowed size for uploaded files, in kilobytes.
|
|
||||||
# Make sure this is an integer, without commas or spaces.
|
|
||||||
DEFAULT_MAX_UPLOAD_SIZE=10240
|
|
||||||
|
|
||||||
# Maximum allowed storage size per account, in megabytes.
|
|
||||||
# Make sure this is an integer, without commas or spaces.
|
|
||||||
DEFAULT_MAX_STORAGE_SIZE=512
|
|
||||||
|
|
||||||
# Default filesystem to store uploaded files.
|
|
||||||
# Possible values: public|s3
|
|
||||||
DEFAULT_FILESYSTEM=public
|
|
||||||
|
|
||||||
# AWS keys for S3 when using this storage method
|
|
||||||
AWS_KEY=
|
|
||||||
AWS_SECRET=
|
|
||||||
AWS_REGION=us-east-1
|
|
||||||
AWS_BUCKET=
|
|
||||||
AWS_SERVER=
|
|
||||||
|
|
||||||
# Allow Two Factor Authentication feature on your instance
|
|
||||||
MFA_ENABLED=true
|
|
||||||
|
|
||||||
# Enable DAV support
|
|
||||||
DAV_ENABLED=true
|
|
||||||
|
|
||||||
# CLIENT ID and SECRET used for OAuth authentication
|
|
||||||
PASSPORT_PERSONAL_ACCESS_CLIENT_ID=
|
|
||||||
PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET=
|
|
||||||
|
|
||||||
# Allow to access general statistics about your instance through a public API
|
|
||||||
# call
|
|
||||||
ALLOW_STATISTICS_THROUGH_PUBLIC_API_ACCESS=false
|
|
||||||
|
|
||||||
# Indicates that each user in the instance must comply to international policies
|
|
||||||
# like CASL or GDPR
|
|
||||||
POLICY_COMPLIANT=true
|
|
||||||
|
|
||||||
# Enable geolocation services
|
|
||||||
# This is used to translate addresses to GPS coordinates.
|
|
||||||
ENABLE_GEOLOCATION=false
|
|
||||||
|
|
||||||
# API key for geolocation services
|
|
||||||
# We use LocationIQ (https://locationiq.com/) to translate addresses to
|
|
||||||
# latitude/longitude coordinates. We could use Google instead but we don't
|
|
||||||
# want to give anything to Google, ever.
|
|
||||||
# LocationIQ offers 10,000 free requests per day.
|
|
||||||
LOCATION_IQ_API_KEY=
|
|
||||||
|
|
||||||
# Enable weather on contact profile page
|
|
||||||
# Weather can only be fetched if we know longitude/latitude - this is why
|
|
||||||
# you also need to activate the geolocation service above to make it work
|
|
||||||
ENABLE_WEATHER=false
|
|
||||||
|
|
||||||
# Access to weather data from darksky api
|
|
||||||
# https://darksky.net/dev/register
|
|
||||||
# Darksky provides an api with 1000 free API calls per day
|
|
||||||
# You need to enable the weather above if you provide an API key here.
|
|
||||||
DARKSKY_API_KEY=
|
|
|
@ -1,58 +0,0 @@
|
||||||
version: '2.4'
|
|
||||||
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
image: 'monica:2.20.0-apache'
|
|
||||||
restart: 'always'
|
|
||||||
|
|
||||||
healthcheck:
|
|
||||||
test: 'curl -f localhost:80 || exit 1'
|
|
||||||
interval: '1m'
|
|
||||||
timeout: '10s'
|
|
||||||
retries: 3
|
|
||||||
start_period: '10s'
|
|
||||||
depends_on:
|
|
||||||
db:
|
|
||||||
condition: 'service_started'
|
|
||||||
redis:
|
|
||||||
condition: 'service_healthy'
|
|
||||||
|
|
||||||
env_file:
|
|
||||||
- '.env'
|
|
||||||
networks:
|
|
||||||
- 'default'
|
|
||||||
- 'nginx'
|
|
||||||
volumes:
|
|
||||||
- 'data:/var/www/html/storage'
|
|
||||||
|
|
||||||
db:
|
|
||||||
image: 'mariadb:10.5.9-focal'
|
|
||||||
restart: 'always'
|
|
||||||
command: '--default-authentication-plugin=mysql_native_password'
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- 'MYSQL_RANDOM_ROOT_PASSWORD=true'
|
|
||||||
- 'MYSQL_DATABASE=monica'
|
|
||||||
- 'MYSQL_USER=monica'
|
|
||||||
- 'MYSQL_PASSWORD=monica'
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
- 'db-data:/var/lib/mysql'
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: 'redis:6.2.2-alpine'
|
|
||||||
restart: 'always'
|
|
||||||
|
|
||||||
healthcheck:
|
|
||||||
test: 'redis-cli -h localhost ping'
|
|
||||||
interval: '10s'
|
|
||||||
timeout: '5s'
|
|
||||||
retries: 3
|
|
||||||
|
|
||||||
networks:
|
|
||||||
nginx:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
data:
|
|
||||||
db-data:
|
|
|
@ -2,7 +2,7 @@
|
||||||
POSTGRES_HOST=db
|
POSTGRES_HOST=db
|
||||||
POSTGRES_DB=nextcloud
|
POSTGRES_DB=nextcloud
|
||||||
POSTGRES_USER=nextcloud
|
POSTGRES_USER=nextcloud
|
||||||
POSTGRES_PASSWORD=nextcloud
|
POSTGRES_PASSWORD=pass
|
||||||
|
|
||||||
# Redis
|
# Redis
|
||||||
REDIS_HOST=redis
|
REDIS_HOST=redis
|
||||||
|
|
|
@ -1,24 +1,17 @@
|
||||||
version: '2.4'
|
version: '3.5'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
image: 'nextcloud:21.0.1-apache'
|
image: 'nextcloud:20-apache'
|
||||||
restart: 'always'
|
restart: 'always'
|
||||||
|
|
||||||
healthcheck:
|
|
||||||
test: 'curl -f localhost || exit 1'
|
|
||||||
interval: '1m'
|
|
||||||
timeout: '10s'
|
|
||||||
retries: 3
|
|
||||||
start_period: '10s'
|
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
- 'db'
|
||||||
condition: 'service_healthy'
|
- 'redis'
|
||||||
redis:
|
|
||||||
condition: 'service_healthy'
|
|
||||||
|
|
||||||
env_file:
|
env_file:
|
||||||
- '.env'
|
- '.env'
|
||||||
|
labels:
|
||||||
|
- 'com.centurylinklabs.watchtower.enable=true'
|
||||||
networks:
|
networks:
|
||||||
- 'default'
|
- 'default'
|
||||||
- 'nginx'
|
- 'nginx'
|
||||||
|
@ -28,41 +21,40 @@ services:
|
||||||
- 'root:/var/www/html'
|
- 'root:/var/www/html'
|
||||||
|
|
||||||
cron:
|
cron:
|
||||||
image: 'nextcloud:21.0.1-apache'
|
image: 'nextcloud:20-apache'
|
||||||
restart: 'always'
|
|
||||||
entrypoint: '/cron.sh'
|
entrypoint: '/cron.sh'
|
||||||
|
restart: 'always'
|
||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
app:
|
- 'app'
|
||||||
condition: 'service_healthy'
|
|
||||||
|
|
||||||
env_file:
|
env_file:
|
||||||
- '.env'
|
- '.env'
|
||||||
|
labels:
|
||||||
|
- 'com.centurylinklabs.watchtower.enable=true'
|
||||||
volumes:
|
volumes:
|
||||||
- 'config:/var/www/html/config'
|
- 'config:/var/www/html/config'
|
||||||
- 'data:/var/www/html/data'
|
- 'data:/var/www/html/data'
|
||||||
- 'root:/var/www/html'
|
- 'root:/var/www/html'
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: 'postgres:13.2-alpine'
|
image: 'postgres:13-alpine'
|
||||||
restart: 'always'
|
restart: 'always'
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
- 'POSTGRES_DB=nextcloud'
|
- 'POSTGRES_DB'
|
||||||
- 'POSTGRES_USER=nextcloud'
|
- 'POSTGRES_USER'
|
||||||
- 'POSTGRES_PASSWORD=nextcloud'
|
- 'POSTGRES_PASSWORD'
|
||||||
|
labels:
|
||||||
|
- 'com.centurylinklabs.watchtower.enable=true'
|
||||||
volumes:
|
volumes:
|
||||||
- 'db-data:/var/lib/postgresql/data'
|
- 'db-data:/var/lib/postgresql/data'
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: 'redis:6.2.2-alpine'
|
image: 'redis:6-alpine'
|
||||||
restart: 'always'
|
restart: 'always'
|
||||||
|
|
||||||
healthcheck:
|
labels:
|
||||||
test: 'redis-cli -h localhost ping'
|
- 'com.centurylinklabs.watchtower.enable=true'
|
||||||
interval: '10s'
|
|
||||||
timeout: '5s'
|
|
||||||
retries: 3
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
nginx:
|
nginx:
|
||||||
|
|
|
@ -1,65 +1,12 @@
|
||||||
# =====COMMON CONFIGURATION=====
|
# Main domain; also name of certificate
|
||||||
## Comma-seperated list of domains to generate certs for
|
MAIN_DOMAIN=
|
||||||
## NOTE: you should only add domains here that aren't used in any of
|
|
||||||
## the specific configurations below
|
# Comma-separated list of other domains which also arrive here
|
||||||
DOMAINS=
|
DOMAINS=
|
||||||
|
|
||||||
## Admin email; used for certificates
|
# Admin email; used for certificates
|
||||||
EMAIL=
|
EMAIL=
|
||||||
|
|
||||||
## HTTP(S) Port
|
# HTTP(S) Port
|
||||||
HTTP_PORT=80
|
HTTP_PORT=80
|
||||||
HTTPS_PORT=443
|
HTTPS_PORT=443
|
||||||
|
|
||||||
|
|
||||||
# =====PER-SERVICE CONFIGURATION=====
|
|
||||||
# Domain name: domain name that points to the instance
|
|
||||||
# Hostname: basically the argument to proxy_pass
|
|
||||||
|
|
||||||
## Firefly III
|
|
||||||
### Domain name
|
|
||||||
FIREFLY_DOMAIN=
|
|
||||||
### Hostname
|
|
||||||
FIREFLY_HOST=firefly_app_1
|
|
||||||
|
|
||||||
## Koel
|
|
||||||
### Domain name
|
|
||||||
KOEL_DOMAIN=
|
|
||||||
### Hostname
|
|
||||||
KOEL_HOST=koel_app_1
|
|
||||||
|
|
||||||
## Miniflux
|
|
||||||
### Domain name
|
|
||||||
MINIFLUX_DOMAIN=
|
|
||||||
### Hostname
|
|
||||||
MINIFLUX_HOST=miniflux_app_1
|
|
||||||
|
|
||||||
## Monica
|
|
||||||
### Domain name
|
|
||||||
MONICA_DOMAIN=
|
|
||||||
### Hostname
|
|
||||||
MONICA_HOST=monica_app_1
|
|
||||||
|
|
||||||
## Nextcloud
|
|
||||||
### Domain name
|
|
||||||
NEXTCLOUD_DOMAIN=
|
|
||||||
### Hostname
|
|
||||||
NEXTCLOUD_HOST=nextcloud_app_1
|
|
||||||
|
|
||||||
## Portainer
|
|
||||||
### Domain name
|
|
||||||
PORTAINER_DOMAIN=
|
|
||||||
### Hostname
|
|
||||||
PORTAINER_HOST=portainer_app_1
|
|
||||||
|
|
||||||
## Gitea
|
|
||||||
### Domain name
|
|
||||||
GITEA_DOMAIN=
|
|
||||||
### Hostname
|
|
||||||
GITEA_HOST=gitea_app_1
|
|
||||||
|
|
||||||
## Podgrab
|
|
||||||
### Domain name
|
|
||||||
PODGRAB_DOMAIN=
|
|
||||||
### Hostname
|
|
||||||
PODGRAB_HOST=podgrab_app_1
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
FROM nginx:stable-alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache certbot
|
||||||
|
|
||||||
|
COPY entrypoint.sh ./entrypoint.sh
|
||||||
|
RUN chmod +x ./entrypoint.sh
|
||||||
|
|
||||||
|
RUN mkdir /var/lib/certbot
|
||||||
|
COPY renew /etc/periodic/weekly/renew
|
||||||
|
RUN chmod +x /etc/periodic/weekly/renew
|
||||||
|
|
||||||
|
# Default.conf file is annoying
|
||||||
|
RUN rm -rf /etc/nginx/conf.d/*
|
||||||
|
|
||||||
|
RUN /usr/sbin/crond -f -d 8 &
|
||||||
|
|
||||||
|
ENTRYPOINT [ "./entrypoint.sh" ]
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
certbot certonly --standalone -d "$MAIN_DOMAIN,$DOMAINS" --email "$EMAIL" -n --agree-tos --expand
|
||||||
|
|
||||||
|
# The original script handles the template subsitution
|
||||||
|
exec /docker-entrypoint.sh nginx -g "daemon off;"
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
python3 -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew --webroot --webroot-path /var/lib/certbot/ --post-hook "/usr/sbin/nginx -s reload"
|
|
@ -1,13 +1,15 @@
|
||||||
version: '2.4'
|
version: '3.5'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
build: './nginx'
|
build: './build'
|
||||||
image: 'nginx-certbot:stable-alpine'
|
image: 'nginx-certbot:stable-alpine'
|
||||||
restart: 'always'
|
|
||||||
|
|
||||||
env_file:
|
environment:
|
||||||
- '.env'
|
- 'DOMAINS'
|
||||||
|
- 'EMAIL'
|
||||||
|
- 'HTTPS_PORT'
|
||||||
|
- 'HTTP_PORT'
|
||||||
|
- 'MAIN_DOMAIN'
|
||||||
networks:
|
networks:
|
||||||
- 'nginx'
|
- 'nginx'
|
||||||
ports:
|
ports:
|
||||||
|
|
|
@ -5,4 +5,4 @@ user nginx nginx;
|
||||||
worker_processes auto;
|
worker_processes auto;
|
||||||
|
|
||||||
# Load config segments
|
# Load config segments
|
||||||
include conf.d/*.conf;
|
include conf.d/*;
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
FROM nginx:1.20.0-alpine
|
|
||||||
|
|
||||||
COPY entrypoint.sh /entrypoint.sh
|
|
||||||
COPY renew /etc/periodic/weekly/renew
|
|
||||||
|
|
||||||
# Install certbot
|
|
||||||
# Remove default configs
|
|
||||||
RUN apk add --no-cache certbot && \
|
|
||||||
rm -rf /etc/nginx/conf.d/*
|
|
||||||
|
|
||||||
ENTRYPOINT [ "./entrypoint.sh" ]
|
|
|
@ -1,19 +0,0 @@
|
||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
# Start cron
|
|
||||||
/usr/sbin/crond -d 8 &
|
|
||||||
|
|
||||||
# Renew all certificates
|
|
||||||
for url in $(env | grep '^[^=]\+_DOMAIN=' | sed 's/^.*\?=\(.*\)$/\1/g') $(echo "$DOMAINS" | sed 's/,/ /g')
|
|
||||||
do
|
|
||||||
certbot certonly \
|
|
||||||
--standalone \
|
|
||||||
-d "$url" \
|
|
||||||
--email "$EMAIL" \
|
|
||||||
-n \
|
|
||||||
--agree-tos \
|
|
||||||
--expand
|
|
||||||
done
|
|
||||||
|
|
||||||
# The original script handles the template subsitution
|
|
||||||
exec /docker-entrypoint.sh nginx -g "daemon off;"
|
|
|
@ -1,7 +0,0 @@
|
||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
python3 -c 'import random; import time; time.sleep(random.random() * 3600)' && \
|
|
||||||
certbot renew \
|
|
||||||
--webroot \
|
|
||||||
--webroot-path /var/lib/certbot/ \
|
|
||||||
--post-hook "/usr/sbin/nginx -s reload"
|
|
|
@ -1,11 +1,6 @@
|
||||||
server {
|
server {
|
||||||
# SSL Key locations
|
listen 443 ssl;
|
||||||
ssl_certificate /etc/letsencrypt/live/${FIREFLY_DOMAIN}/fullchain.pem;
|
server_name DOMAIN;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${FIREFLY_DOMAIN}/privkey.pem;
|
|
||||||
|
|
||||||
listen ${HTTPS_PORT} ssl;
|
|
||||||
listen [::]:${HTTPS_PORT} ssl;
|
|
||||||
server_name ${FIREFLY_DOMAIN};
|
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
|
@ -18,7 +13,7 @@ server {
|
||||||
proxy_set_header Connection "upgrade";
|
proxy_set_header Connection "upgrade";
|
||||||
|
|
||||||
resolver 127.0.0.11;
|
resolver 127.0.0.11;
|
||||||
proxy_pass http://${FIREFLY_HOST}:8080;
|
proxy_pass http://firefly_app_1:8080;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
server {
|
|
||||||
# SSL Key locations
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${GITEA_DOMAIN}/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${GITEA_DOMAIN}/privkey.pem;
|
|
||||||
|
|
||||||
listen ${HTTPS_PORT} ssl;
|
|
||||||
listen [::]:${HTTPS_PORT} ssl;
|
|
||||||
server_name ${GITEA_DOMAIN};
|
|
||||||
|
|
||||||
location / {
|
|
||||||
resolver 127.0.0.11;
|
|
||||||
proxy_pass http://#{GITEA_HOST}:3000/;
|
|
||||||
|
|
||||||
# Static content caching
|
|
||||||
location ~* \.(?:jpg|jpeg|png|gif|ico|css|js|ttf)$ {
|
|
||||||
expires 1h;
|
|
||||||
add_header Cache-Control public;
|
|
||||||
|
|
||||||
proxy_pass http://${GITEA_HOST}:3000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name DOMAIN;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
resolver 127.0.0.11;
|
||||||
|
proxy_pass http://koel_app_1:80;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,21 +0,0 @@
|
||||||
server {
|
|
||||||
# SSL Key locations
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${KOEL_DOMAIN}/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${KOEL_DOMAIN}/privkey.pem;
|
|
||||||
|
|
||||||
listen ${HTTPS_PORT} ssl;
|
|
||||||
listen [::]:${HTTPS_PORT} ssl;
|
|
||||||
server_name ${KOEL_DOMAIN};
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Host $server_name;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Forwarded-Ssl on;
|
|
||||||
|
|
||||||
resolver 127.0.0.11;
|
|
||||||
proxy_pass http://${KOEL_HOST}:80;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name DOMAIN;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
resolver 127.0.0.11;
|
||||||
|
proxy_pass http://miniflux_app_1:8080;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
server {
|
|
||||||
# SSL Key locations
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${MINIFLUX_DOMAIN}/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${MINIFLUX_DOMAIN}/privkey.pem;
|
|
||||||
|
|
||||||
listen ${HTTPS_PORT} ssl;
|
|
||||||
listen [::]:${HTTPS_PORT} ssl;
|
|
||||||
server_name ${MINIFLUX_DOMAIN};
|
|
||||||
|
|
||||||
location / {
|
|
||||||
resolver 127.0.0.11;
|
|
||||||
proxy_pass http://${MINIFLUX_HOST}:8080;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
server {
|
|
||||||
# SSL Key locations
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${MONICA_DOMAIN}/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${MONICA_DOMAIN}/privkey.pem;
|
|
||||||
|
|
||||||
listen ${HTTPS_PORT} ssl;
|
|
||||||
listen [::]:${HTTPS_PORT} ssl;
|
|
||||||
server_name ${MONICA_DOMAIN};
|
|
||||||
|
|
||||||
client_max_body_size 1G;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Host $server_name;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Forwarded-Ssl on;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "upgrade";
|
|
||||||
|
|
||||||
resolver 127.0.0.11;
|
|
||||||
proxy_pass http://${MONICA_HOST}:80;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +1,7 @@
|
||||||
server {
|
server {
|
||||||
# SSL Key locations
|
listen 443 ssl;
|
||||||
ssl_certificate /etc/letsencrypt/live/${NEXTCLOUD_DOMAIN}/fullchain.pem;
|
listen [::]:443 ssl http2;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${NEXTCLOUD_DOMAIN}/privkey.pem;
|
server_name DOMAIN;
|
||||||
|
|
||||||
listen ${HTTPS_PORT} ssl;
|
|
||||||
# Not sure why http2 is here, but let's keep it just in case
|
|
||||||
listen [::]:${HTTPS_PORT} ssl http2;
|
|
||||||
server_name ${NEXTCLOUD_DOMAIN};
|
|
||||||
|
|
||||||
# Enable gzip but do not remove ETag headers
|
# Enable gzip but do not remove ETag headers
|
||||||
gzip on;
|
gzip on;
|
||||||
|
@ -28,7 +23,7 @@ server {
|
||||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
proxy_pass http://${NEXTCLOUD_HOST}:80/;
|
proxy_pass http://nextcloud_app_1:80/;
|
||||||
|
|
||||||
proxy_pass_request_headers on;
|
proxy_pass_request_headers on;
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
server {
|
|
||||||
# SSL Key locations
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${PODGRAB_DOMAIN}/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${PODGRAB_DOMAIN}/privkey.pem;
|
|
||||||
listen ${HTTPS_PORT} ssl;
|
|
||||||
listen [::]:${HTTPS_PORT} ssl;
|
|
||||||
|
|
||||||
server_name ${PODGRAB_DOMAIN};
|
|
||||||
|
|
||||||
location / {
|
|
||||||
resolver 127.0.0.11;
|
|
||||||
proxy_pass http://${PODGRAB_HOST}:8080/;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name DOMAIN;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
|
||||||
|
resolver 127.0.0.11;
|
||||||
|
proxy_pass http://portainer_app_1:9000;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +0,0 @@
|
||||||
server {
|
|
||||||
# SSL Key locations
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${PORTAINER_DOMAIN}/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${PORTAINER_DOMAIN}/privkey.pem;
|
|
||||||
|
|
||||||
listen ${HTTPS_PORT} ssl;
|
|
||||||
listen [::]:${HTTPS_PORT} ssl;
|
|
||||||
server_name ${PORTAINER_DOMAIN};
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_set_header Connection "upgrade";
|
|
||||||
|
|
||||||
resolver 127.0.0.11;
|
|
||||||
proxy_pass http://${PORTAINER_HOST}:9000;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,9 @@
|
||||||
http {
|
http {
|
||||||
# COMMON SSL CONFIGURATION
|
# SSL CONFIGURATION
|
||||||
|
# Key locations
|
||||||
|
ssl_certificate /etc/letsencrypt/live/${MAIN_DOMAIN}/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/${MAIN_DOMAIN}/privkey.pem;
|
||||||
|
|
||||||
# Allowed protocols
|
# Allowed protocols
|
||||||
ssl_protocols TLSv1.2;
|
ssl_protocols TLSv1.2;
|
||||||
|
|
||||||
|
@ -25,6 +29,7 @@ http {
|
||||||
return 301 https://$host:${HTTPS_PORT}$request_uri;
|
return 301 https://$host:${HTTPS_PORT}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# LOAD SITES
|
# LOAD SITES
|
||||||
include conf.d/sites-enabled/*.conf;
|
include sites-enabled/*.conf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
*
|
|
||||||
|
|
||||||
!.gitignore
|
|
|
@ -1,5 +0,0 @@
|
||||||
# How often to check for new episodes in seconds
|
|
||||||
CHECK_FREQUENCY=240
|
|
||||||
|
|
||||||
# Password the basic auth
|
|
||||||
PASSWORD=changeme
|
|
|
@ -1,29 +0,0 @@
|
||||||
version: '2.4'
|
|
||||||
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
image: 'akhilrex/podgrab:1.0.0'
|
|
||||||
restart: 'always'
|
|
||||||
|
|
||||||
healthcheck:
|
|
||||||
test: 'curl -f localhost:8080 || exit 1'
|
|
||||||
interval: '1m'
|
|
||||||
timeout: '10s'
|
|
||||||
retries: 3
|
|
||||||
start_period: '10s'
|
|
||||||
|
|
||||||
env_file:
|
|
||||||
- '.env'
|
|
||||||
networks:
|
|
||||||
- 'nginx'
|
|
||||||
volumes:
|
|
||||||
- 'config:/config'
|
|
||||||
- 'assets:/assets'
|
|
||||||
|
|
||||||
networks:
|
|
||||||
nginx:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
config:
|
|
||||||
assets:
|
|
|
@ -1,17 +1,12 @@
|
||||||
version: '2.4'
|
version: '3.5'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
image: 'portainer/portainer-ce:2.1.1-alpine'
|
image: 'portainer/portainer-ce:latest'
|
||||||
restart: 'always'
|
restart: 'always'
|
||||||
|
|
||||||
healthcheck:
|
labels:
|
||||||
test: 'curl -f localhost:9000 || exit 1'
|
- 'com.centurylinklabs.watchtower.enable=true'
|
||||||
interval: '1m'
|
|
||||||
timeout: '10s'
|
|
||||||
retries: 3
|
|
||||||
start_period: '10s'
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
- 'nginx'
|
- 'nginx'
|
||||||
ports:
|
ports:
|
||||||
|
@ -22,7 +17,8 @@ services:
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
nginx:
|
nginx:
|
||||||
external: true
|
external:
|
||||||
|
name: 'nginx'
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
data:
|
data:
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
|
|
||||||
}
|
|
|
@ -1,15 +1,29 @@
|
||||||
# What version of TShock to use
|
# Copyright (C) 2020 Jef Roosens
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
# Build arguments
|
||||||
RELEASE_TAG=
|
RELEASE_TAG=
|
||||||
|
|
||||||
# What world size to create:
|
# Environment variables
|
||||||
# 1 for small, 2 for medium, 3 for large
|
|
||||||
AUTOCREATE=2
|
AUTOCREATE=2
|
||||||
|
|
||||||
# Mount points for the data directories
|
# Mount points
|
||||||
# By default, it creates volumes
|
CONFIG_DIR=
|
||||||
CONFIG_DIR=config
|
LOGS_DIR=
|
||||||
LOGS_DIR=logs
|
WORLDS_DIR=
|
||||||
WORLDS_DIR=worlds
|
|
||||||
|
|
||||||
# The port to publish the server on
|
# Other
|
||||||
PORT=7777
|
PORT=7777
|
||||||
|
|
|
@ -1,20 +1,42 @@
|
||||||
FROM alpine:3.13.5 AS base
|
# Copyright (C) 2020 Jef Roosens
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
FROM alpine:latest AS base
|
||||||
|
|
||||||
# Build arguments
|
# Build arguments
|
||||||
ARG RELEASE_TAG
|
ARG RELEASE_TAG
|
||||||
|
|
||||||
|
# Add unzip & curl
|
||||||
|
RUN apk update && apk add --no-cache unzip curl
|
||||||
|
|
||||||
WORKDIR /terraria
|
WORKDIR /terraria
|
||||||
|
|
||||||
RUN apk update && apk add --no-cache unzip curl && \
|
# Download & unzip
|
||||||
curl -s "https://api.github.com/repos/Pryaxis/TShock/releases/tags/${RELEASE_TAG}" | \
|
# TODO convert this to jq?
|
||||||
|
RUN curl -s "https://api.github.com/repos/Pryaxis/TShock/releases/tags/${RELEASE_TAG}" | \
|
||||||
grep "browser_download_url" | \
|
grep "browser_download_url" | \
|
||||||
grep -o "https[^\"]\+" | \
|
grep -o "https[^\"]\+" | \
|
||||||
xargs curl -sLo tshock.zip && \
|
xargs curl -sLo tshock.zip && \
|
||||||
unzip -d tshock tshock.zip && \
|
unzip tshock.zip && \
|
||||||
rm tshock.zip
|
rm tshock.zip && \
|
||||||
|
# Is there a better way to do this?
|
||||||
|
mv TShock* tshock
|
||||||
|
|
||||||
|
|
||||||
FROM mono:6.12.0.107
|
FROM mono:latest
|
||||||
WORKDIR /terraria
|
WORKDIR /terraria
|
||||||
|
|
||||||
COPY --from=base /terraria/tshock /terraria
|
COPY --from=base /terraria/tshock /terraria
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
<!---
|
||||||
|
|
||||||
|
Copyright (C) 2020 Jef Roosens
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
# Build arguments
|
# Build arguments
|
||||||
The only required build argument is `RELEASE_TAG`. This is the GitHub tag of
|
The only required build argument is `RELEASE_TAG`. This is the GitHub tag of
|
||||||
the release you wish to use. The releases can be found
|
the release you wish to use. The releases can be found
|
||||||
|
|
|
@ -1,25 +1,37 @@
|
||||||
version: '2.4'
|
# Copyright (C) 2020 Jef Roosens
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
version: '3.5'
|
||||||
services:
|
services:
|
||||||
app:
|
tshock:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
args:
|
args:
|
||||||
- 'RELEASE_TAG=${RELEASE_TAG}'
|
- 'RELEASE_TAG=${RELEASE_TAG}'
|
||||||
image: 'chewingbever/terraria-tshock:${RELEASE_TAG}'
|
image: 'terraria-tshock:${RELEASE_TAG}'
|
||||||
restart: 'always'
|
|
||||||
|
restart: 'unless-stopped'
|
||||||
stdin_open: true
|
stdin_open: true
|
||||||
tty: true
|
tty: true
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
- 'AUTOCREATE'
|
- AUTOCREATE
|
||||||
ports:
|
ports:
|
||||||
- '$PORT:7777'
|
- '$PORT:7777'
|
||||||
volumes:
|
volumes:
|
||||||
- '$CONFIG_DIR:/terraria/config'
|
- '$CONFIG_DIR:/terraria/config'
|
||||||
- '$LOGS_DIR:/terraria/logs'
|
- '$LOGS_DIR:/terraria/logs'
|
||||||
- '$WORLDS_DIR:/terraria/worlds'
|
- '$WORLDS_DIR:/terraria/worlds'
|
||||||
|
|
||||||
volumes:
|
|
||||||
config:
|
|
||||||
logs:
|
|
||||||
worlds:
|
|
||||||
|
|
Reference in New Issue