diff --git a/README.md b/README.md index 6ef5b35..72ab414 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,5 @@ - - - # self-hosting + # Contents The repo contains setup guides for the following: @@ -35,9 +16,11 @@ Each directory contains (or will contain) its own `README.md` to aid with the installation of that specific setup. # General info + This info applies to all configs. ## Docker + 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 package manager (do note that the Docker package might be called `docker.io`). @@ -45,23 +28,27 @@ Otherwise, the install instructions can be found [here](https://docs.docker.com/engine/install/). ## Configuration + 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 compose files, unless you wish to deviate from the default format. ## Building the image + 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 build configuration/environment variables can be defined in a `.env` file. A `.env.example` file is given for each configuration. ## Running the container + 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 `docker-compose logs`. If you want the logs to update automatically, use `docker-compose logs -f`. # Why did I make this? + 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 and figuring out how they work best (for me at least), and wanted to share this diff --git a/backups/.gitignore b/backups/.gitignore deleted file mode 100644 index 205abbb..0000000 --- a/backups/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -__pycache__/ -backup_tool diff --git a/backups/README.md b/backups/README.md deleted file mode 100644 index 3edfd50..0000000 --- a/backups/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# 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. diff --git a/backups/app/__main__.py b/backups/app/__main__.py deleted file mode 100644 index 535d616..0000000 --- a/backups/app/__main__.py +++ /dev/null @@ -1,41 +0,0 @@ -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() diff --git a/backups/app/notifier.py b/backups/app/notifier.py deleted file mode 100644 index e69de29..0000000 diff --git a/backups/app/specs/__init__.py b/backups/app/specs/__init__.py deleted file mode 100644 index 5104164..0000000 --- a/backups/app/specs/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .specs import Spec -from .parser import parse_specs_file diff --git a/backups/app/specs/parser.py b/backups/app/specs/parser.py deleted file mode 100644 index fab362a..0000000 --- a/backups/app/specs/parser.py +++ /dev/null @@ -1,114 +0,0 @@ -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 diff --git a/backups/app/specs/specs.py b/backups/app/specs/specs.py deleted file mode 100644 index f2971ca..0000000 --- a/backups/app/specs/specs.py +++ /dev/null @@ -1,146 +0,0 @@ -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"] - ) diff --git a/backups/backups.yaml.example b/backups/backups.yaml.example deleted file mode 100644 index 68a203b..0000000 --- a/backups/backups.yaml.example +++ /dev/null @@ -1,15 +0,0 @@ -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 diff --git a/backups/install.sh b/backups/install.sh deleted file mode 100755 index d846c29..0000000 --- a/backups/install.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/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 diff --git a/firefly/.env.example b/firefly/.env.example index 164c22c..58202bb 100644 --- a/firefly/.env.example +++ b/firefly/.env.example @@ -63,7 +63,7 @@ DB_HOST=db DB_PORT=5432 DB_DATABASE=firefly DB_USERNAME=firefly -DB_PASSWORD=password +DB_PASSWORD=firefly # 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 diff --git a/firefly/docker-compose.yml b/firefly/docker-compose.yml index 65e501e..7547831 100644 --- a/firefly/docker-compose.yml +++ b/firefly/docker-compose.yml @@ -1,4 +1,4 @@ -version: '2.8' +version: '2.4' services: app: @@ -6,24 +6,23 @@ services: context: '.' args: - 'LOCALE=$DEFAULT_LOCALE' - image: 'firefly-iii-cron:latest' + image: 'chewingbever/firefly-iii-cron:latest' restart: 'always' + healthcheck: test: 'curl -f localhost:8080 || exit 1' interval: '1m' timeout: '10s' retries: 3 start_period: '10s' - depends_on: db: condition: 'service_healthy' redis: condition: 'service_healthy' + env_file: - '.env' - labels: - - 'com.centurylinklabs.watchtower.enable=true' networks: - 'nginx' - 'default' @@ -31,35 +30,33 @@ services: - 'upload:/var/www/html/storage/upload' db: - image: 'postgres:13-alpine' + image: 'postgres:13.2-alpine' restart: 'always' + healthcheck: - test: 'pg_isready -U $DB_USERNAME' + test: 'pg_isready -U firefly' interval: '10s' timeout: '5s' retries: 5 + start_period: '0s' environment: - - 'POSTGRES_DB=$DB_DATABASE' - - 'POSTGRES_PASSWORD=$DB_PASSWORD' - - 'POSTGRES_USER=$DB_USERNAME' - labels: - - 'com.centurylinklabs.watchtower.enable=true' + - 'POSTGRES_DB=firefly' + - 'POSTGRES_PASSWORD=firefly' + - 'POSTGRES_USER=firefly' volumes: - 'db-data:/var/lib/postgresql/data' redis: - image: 'redis:6-alpine' + image: 'redis:6.2.2-alpine' restart: 'always' + healthcheck: test: 'redis-cli -h localhost ping' interval: '10s' timeout: '5s' retries: 3 - labels: - - 'com.centurylinklabs.watchtower.enable=true' - networks: nginx: external: true diff --git a/gitea/.env.example b/gitea/.env.example new file mode 100644 index 0000000..95e1324 --- /dev/null +++ b/gitea/.env.example @@ -0,0 +1,16 @@ +# 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 diff --git a/gitea/docker-compose.yml b/gitea/docker-compose.yml new file mode 100644 index 0000000..6e65af8 --- /dev/null +++ b/gitea/docker-compose.yml @@ -0,0 +1,59 @@ +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: diff --git a/koel/.env.example b/koel/.env.example index d58e408..9ba0882 100644 --- a/koel/.env.example +++ b/koel/.env.example @@ -12,7 +12,7 @@ DB_HOST=db DB_PORT=3306 DB_DATABASE=koel DB_USERNAME=koel -DB_PASSWORD=changeme +DB_PASSWORD=koel # A random 32-char string. You can leave this empty if use php artisan koel:init. APP_KEY= diff --git a/koel/docker-compose.yml b/koel/docker-compose.yml index 19d6e1a..c207d71 100644 --- a/koel/docker-compose.yml +++ b/koel/docker-compose.yml @@ -1,14 +1,22 @@ -version: '3.5' +version: '2.4' services: app: + # This repository sadly only has a 'latest' flag image: 'hyzual/koel:latest' restart: 'always' + healthcheck: + test: 'curl -f localhost:80 || exit 1' + interval: '1m' + timeout: '10s' + retries: 3 + start_period: '10s' depends_on: - - 'db' - labels: - - 'com.centurylinklabs.watchtower.enable=true' + db: + # Haven't found a good MySQL healthcheck yet + condition: 'service_started' + networks: - 'default' - 'nginx' @@ -16,19 +24,18 @@ services: - './.env:/var/www/html/.env' - 'covers:/var/www/html/public/img/covers' - 'music:/music' + - 'index:/var/www/html/storage/search-indexes' db: - image: 'mysql:8' + image: 'mariadb:10.5.9-focal' restart: 'always' command: '--default-authentication-plugin=mysql_native_password' environment: - 'MYSQL_DATABASE=koel' - - 'MYSQL_PASSWORD=$DB_PASSWORD' - - 'MYSQL_ROOT_PASSWORD=$DB_PASSWORD' - - 'MYSQL_USER=$DB_USERNAME' - labels: - - 'com.centurylinklabs.watchtower.enable=true' + - 'MYSQL_USER=koel' + - 'MYSQL_PASSWORD=koel' + - 'MYSQL_RANDOM_ROOT_PASSWORD=yes' volumes: - 'db-data:/var/lib/mysql' @@ -39,4 +46,5 @@ networks: volumes: covers: db-data: + index: music: diff --git a/minecraft/fabric/docker-compose.yml b/minecraft/fabric/docker-compose.yml index 28d43bf..440ad2b 100644 --- a/minecraft/fabric/docker-compose.yml +++ b/minecraft/fabric/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.5' +version: '2.0' services: app: build: diff --git a/minecraft/forge/docker-compose.yml b/minecraft/forge/docker-compose.yml index f8077d2..95ba6e4 100644 --- a/minecraft/forge/docker-compose.yml +++ b/minecraft/forge/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.5' +version: '2.0' services: app: build: diff --git a/minecraft/papermc/docker-compose.yml b/minecraft/papermc/docker-compose.yml index fd4afec..c9a41bc 100644 --- a/minecraft/papermc/docker-compose.yml +++ b/minecraft/papermc/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.5' +version: '2.0' services: app: build: @@ -7,7 +7,7 @@ services: - 'BASE_IMAGE' - 'MC_VERSION' - 'PAPERMC_VERSION' - image: 'chewingbever/mc-papermc:${MC_VERSION}-${PAPERMC_VERSION}' + image: 'localhost:5000/mc-papermc:${MC_VERSION}-${PAPERMC_VERSION}' restart: 'always' # Needed to interact with server console diff --git a/miniflux/miniflux.env.example b/miniflux/.env.example similarity index 63% rename from miniflux/miniflux.env.example rename to miniflux/.env.example index 161f6c8..0a429a9 100644 --- a/miniflux/miniflux.env.example +++ b/miniflux/.env.example @@ -1,5 +1,4 @@ # Database settings -DATABASE_URL=postgres://miniflux:changeme@db/miniflux?sslmode=disable RUN_MIGRATIONS=1 # Auto-create admin user diff --git a/miniflux/db.env.example b/miniflux/db.env.example deleted file mode 100644 index 79ebaff..0000000 --- a/miniflux/db.env.example +++ /dev/null @@ -1,3 +0,0 @@ -POSTGRES_DB=miniflux -POSTGRES_USER=miniflux -POSTGRES_PASSWORD=changeme diff --git a/miniflux/docker-compose.yml b/miniflux/docker-compose.yml index 4a59057..24aae5a 100644 --- a/miniflux/docker-compose.yml +++ b/miniflux/docker-compose.yml @@ -1,28 +1,44 @@ -version: '3.5' +version: '2.4' services: app: - image: 'miniflux/miniflux:latest' + image: 'miniflux/miniflux:2.0.29' restart: 'always' 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: - - 'miniflux.env' - labels: - - 'com.centurylinklabs.watchtower.enable=true' + - '.env' + environment: + # This is always the same, so we just put it here + - 'DATABASE_URL=postgres://miniflux:miniflux@db/miniflux?sslmode=disable' networks: - 'default' - 'nginx' db: - image: 'postgres:13-alpine' + image: 'postgres:13.2-alpine' restart: 'always' - env_file: - - 'db.env' - labels: - - 'com.centurylinklabs.watchtower.enable=true' + healthcheck: + test: 'pg_isready -U miniflux' + interval: '10s' + timeout: '5s' + retries: 5 + start_period: '0s' + + environment: + - 'POSTGRES_DB=miniflux' + - 'POSTGRES_USER=miniflux' + - 'POSTGRES_PASSWORD=miniflux' volumes: - 'db-data:/var/lib/postgresql/data' diff --git a/monica/.env.example b/monica/.env.example new file mode 100644 index 0000000..27ad3e7 --- /dev/null +++ b/monica/.env.example @@ -0,0 +1,168 @@ +# +# 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= diff --git a/monica/docker-compose.yml b/monica/docker-compose.yml new file mode 100644 index 0000000..2556e8e --- /dev/null +++ b/monica/docker-compose.yml @@ -0,0 +1,58 @@ +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: diff --git a/nextcloud/.env.example b/nextcloud/.env.example index 526887b..2c43195 100644 --- a/nextcloud/.env.example +++ b/nextcloud/.env.example @@ -2,7 +2,7 @@ POSTGRES_HOST=db POSTGRES_DB=nextcloud POSTGRES_USER=nextcloud -POSTGRES_PASSWORD=pass +POSTGRES_PASSWORD=nextcloud # Redis REDIS_HOST=redis diff --git a/nextcloud/docker-compose.yml b/nextcloud/docker-compose.yml index b287465..bb6be0d 100644 --- a/nextcloud/docker-compose.yml +++ b/nextcloud/docker-compose.yml @@ -1,17 +1,24 @@ -version: '3.5' +version: '2.4' services: app: - image: 'nextcloud:20-apache' + image: 'nextcloud:21.0.1-apache' restart: 'always' + healthcheck: + test: 'curl -f localhost || exit 1' + interval: '1m' + timeout: '10s' + retries: 3 + start_period: '10s' depends_on: - - 'db' - - 'redis' + db: + condition: 'service_healthy' + redis: + condition: 'service_healthy' + env_file: - '.env' - labels: - - 'com.centurylinklabs.watchtower.enable=true' networks: - 'default' - 'nginx' @@ -21,40 +28,41 @@ services: - 'root:/var/www/html' cron: - image: 'nextcloud:20-apache' - entrypoint: '/cron.sh' + image: 'nextcloud:21.0.1-apache' restart: 'always' + entrypoint: '/cron.sh' depends_on: - - 'app' + app: + condition: 'service_healthy' + env_file: - '.env' - labels: - - 'com.centurylinklabs.watchtower.enable=true' volumes: - 'config:/var/www/html/config' - 'data:/var/www/html/data' - 'root:/var/www/html' db: - image: 'postgres:13-alpine' + image: 'postgres:13.2-alpine' restart: 'always' environment: - - 'POSTGRES_DB' - - 'POSTGRES_USER' - - 'POSTGRES_PASSWORD' - labels: - - 'com.centurylinklabs.watchtower.enable=true' + - 'POSTGRES_DB=nextcloud' + - 'POSTGRES_USER=nextcloud' + - 'POSTGRES_PASSWORD=nextcloud' volumes: - 'db-data:/var/lib/postgresql/data' redis: - image: 'redis:6-alpine' + image: 'redis:6.2.2-alpine' restart: 'always' - labels: - - 'com.centurylinklabs.watchtower.enable=true' + healthcheck: + test: 'redis-cli -h localhost ping' + interval: '10s' + timeout: '5s' + retries: 3 networks: nginx: diff --git a/nginx/.env.example b/nginx/.env.example index 445e483..d63211e 100644 --- a/nginx/.env.example +++ b/nginx/.env.example @@ -1,12 +1,65 @@ -# Main domain; also name of certificate -MAIN_DOMAIN= - -# Comma-separated list of other domains which also arrive here +# =====COMMON CONFIGURATION===== +## Comma-seperated list of domains to generate certs for +## NOTE: you should only add domains here that aren't used in any of +## the specific configurations below DOMAINS= -# Admin email; used for certificates +## Admin email; used for certificates EMAIL= -# HTTP(S) Port +## HTTP(S) Port HTTP_PORT=80 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 diff --git a/nginx/build/Dockerfile b/nginx/build/Dockerfile deleted file mode 100644 index 309ea38..0000000 --- a/nginx/build/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -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" ] diff --git a/nginx/build/entrypoint.sh b/nginx/build/entrypoint.sh deleted file mode 100644 index d652550..0000000 --- a/nginx/build/entrypoint.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/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;" diff --git a/nginx/build/renew b/nginx/build/renew deleted file mode 100644 index 98327d4..0000000 --- a/nginx/build/renew +++ /dev/null @@ -1,3 +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" diff --git a/nginx/docker-compose.yml b/nginx/docker-compose.yml index c8e51f1..f991d1b 100644 --- a/nginx/docker-compose.yml +++ b/nginx/docker-compose.yml @@ -1,15 +1,13 @@ -version: '3.5' +version: '2.4' + services: app: - build: './build' + build: './nginx' image: 'nginx-certbot:stable-alpine' + restart: 'always' - environment: - - 'DOMAINS' - - 'EMAIL' - - 'HTTPS_PORT' - - 'HTTP_PORT' - - 'MAIN_DOMAIN' + env_file: + - '.env' networks: - 'nginx' ports: diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 6f321f0..c3e3167 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -5,4 +5,4 @@ user nginx nginx; worker_processes auto; # Load config segments -include conf.d/*; +include conf.d/*.conf; diff --git a/nginx/nginx/Dockerfile b/nginx/nginx/Dockerfile new file mode 100644 index 0000000..19a359b --- /dev/null +++ b/nginx/nginx/Dockerfile @@ -0,0 +1,11 @@ +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" ] diff --git a/nginx/nginx/entrypoint.sh b/nginx/nginx/entrypoint.sh new file mode 100755 index 0000000..1205a79 --- /dev/null +++ b/nginx/nginx/entrypoint.sh @@ -0,0 +1,19 @@ +#!/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;" diff --git a/nginx/nginx/renew b/nginx/nginx/renew new file mode 100755 index 0000000..bdbebcf --- /dev/null +++ b/nginx/nginx/renew @@ -0,0 +1,7 @@ +#!/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" diff --git a/nginx/sites-available/firefly-iii.conf b/nginx/sites-available/firefly-iii.conf.template similarity index 60% rename from nginx/sites-available/firefly-iii.conf rename to nginx/sites-available/firefly-iii.conf.template index 1a9f1c4..e9447fc 100644 --- a/nginx/sites-available/firefly-iii.conf +++ b/nginx/sites-available/firefly-iii.conf.template @@ -1,6 +1,11 @@ server { - listen 443 ssl; - server_name DOMAIN; + # SSL Key locations + ssl_certificate /etc/letsencrypt/live/${FIREFLY_DOMAIN}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/${FIREFLY_DOMAIN}/privkey.pem; + + listen ${HTTPS_PORT} ssl; + listen [::]:${HTTPS_PORT} ssl; + server_name ${FIREFLY_DOMAIN}; location / { proxy_set_header Host $host; @@ -13,7 +18,7 @@ server { proxy_set_header Connection "upgrade"; resolver 127.0.0.11; - proxy_pass http://firefly_app_1:8080; + proxy_pass http://${FIREFLY_HOST}:8080; } } diff --git a/nginx/sites-available/gitea.conf.template b/nginx/sites-available/gitea.conf.template new file mode 100644 index 0000000..477f4be --- /dev/null +++ b/nginx/sites-available/gitea.conf.template @@ -0,0 +1,23 @@ +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; + } + } +} + diff --git a/nginx/sites-available/koel.conf b/nginx/sites-available/koel.conf deleted file mode 100644 index 82832a5..0000000 --- a/nginx/sites-available/koel.conf +++ /dev/null @@ -1,9 +0,0 @@ -server { - listen 443 ssl; - server_name DOMAIN; - - location / { - resolver 127.0.0.11; - proxy_pass http://koel_app_1:80; - } -} diff --git a/nginx/sites-available/koel.conf.template b/nginx/sites-available/koel.conf.template new file mode 100644 index 0000000..93f4fc5 --- /dev/null +++ b/nginx/sites-available/koel.conf.template @@ -0,0 +1,21 @@ +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; + } +} diff --git a/nginx/sites-available/miniflux.conf b/nginx/sites-available/miniflux.conf deleted file mode 100644 index da25654..0000000 --- a/nginx/sites-available/miniflux.conf +++ /dev/null @@ -1,10 +0,0 @@ -server { - listen 443 ssl; - server_name DOMAIN; - - location / { - resolver 127.0.0.11; - proxy_pass http://miniflux_app_1:8080; - } -} - diff --git a/nginx/sites-available/miniflux.conf.template b/nginx/sites-available/miniflux.conf.template new file mode 100644 index 0000000..eefbe26 --- /dev/null +++ b/nginx/sites-available/miniflux.conf.template @@ -0,0 +1,15 @@ +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; + } +} + diff --git a/nginx/sites-available/monica.conf.template b/nginx/sites-available/monica.conf.template new file mode 100644 index 0000000..05e5803 --- /dev/null +++ b/nginx/sites-available/monica.conf.template @@ -0,0 +1,25 @@ +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; + } +} diff --git a/nginx/sites-available/nefarious.conf b/nginx/sites-available/nefarious.conf.template similarity index 100% rename from nginx/sites-available/nefarious.conf rename to nginx/sites-available/nefarious.conf.template diff --git a/nginx/sites-available/nextcloud.conf b/nginx/sites-available/nextcloud.conf.template similarity index 84% rename from nginx/sites-available/nextcloud.conf rename to nginx/sites-available/nextcloud.conf.template index e36549d..9ade02e 100644 --- a/nginx/sites-available/nextcloud.conf +++ b/nginx/sites-available/nextcloud.conf.template @@ -1,7 +1,12 @@ server { - listen 443 ssl; - listen [::]:443 ssl http2; - server_name DOMAIN; + # SSL Key locations + ssl_certificate /etc/letsencrypt/live/${NEXTCLOUD_DOMAIN}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/${NEXTCLOUD_DOMAIN}/privkey.pem; + + 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 gzip on; @@ -23,7 +28,7 @@ server { add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; location / { - proxy_pass http://nextcloud_app_1:80/; + proxy_pass http://${NEXTCLOUD_HOST}:80/; proxy_pass_request_headers on; diff --git a/nginx/sites-available/podgrab.conf.template b/nginx/sites-available/podgrab.conf.template new file mode 100644 index 0000000..81ef710 --- /dev/null +++ b/nginx/sites-available/podgrab.conf.template @@ -0,0 +1,15 @@ +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/; + } +} + diff --git a/nginx/sites-available/portainer.conf b/nginx/sites-available/portainer.conf deleted file mode 100644 index 98b1e44..0000000 --- a/nginx/sites-available/portainer.conf +++ /dev/null @@ -1,11 +0,0 @@ -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; - } -} diff --git a/nginx/sites-available/portainer.conf.template b/nginx/sites-available/portainer.conf.template new file mode 100644 index 0000000..c9ec72c --- /dev/null +++ b/nginx/sites-available/portainer.conf.template @@ -0,0 +1,16 @@ +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; + } +} diff --git a/nginx/templates/http.conf.template b/nginx/templates/http.conf.template index 2b62f29..bd928c6 100644 --- a/nginx/templates/http.conf.template +++ b/nginx/templates/http.conf.template @@ -1,9 +1,5 @@ http { - # SSL CONFIGURATION - # Key locations - ssl_certificate /etc/letsencrypt/live/${MAIN_DOMAIN}/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/${MAIN_DOMAIN}/privkey.pem; - + # COMMON SSL CONFIGURATION # Allowed protocols ssl_protocols TLSv1.2; @@ -29,7 +25,6 @@ http { return 301 https://$host:${HTTPS_PORT}$request_uri; } - # LOAD SITES - include sites-enabled/*.conf; + include conf.d/sites-enabled/*.conf; } diff --git a/nginx/templates/sites-enabled/.gitignore b/nginx/templates/sites-enabled/.gitignore new file mode 100644 index 0000000..cec9082 --- /dev/null +++ b/nginx/templates/sites-enabled/.gitignore @@ -0,0 +1,3 @@ +* + +!.gitignore diff --git a/podgrab/.env.example b/podgrab/.env.example new file mode 100644 index 0000000..6c69f28 --- /dev/null +++ b/podgrab/.env.example @@ -0,0 +1,5 @@ +# How often to check for new episodes in seconds +CHECK_FREQUENCY=240 + +# Password the basic auth +PASSWORD=changeme diff --git a/podgrab/docker-compose.yml b/podgrab/docker-compose.yml new file mode 100644 index 0000000..47e3707 --- /dev/null +++ b/podgrab/docker-compose.yml @@ -0,0 +1,29 @@ +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: diff --git a/portainer/docker-compose.yml b/portainer/docker-compose.yml index 31b62b3..88165b0 100644 --- a/portainer/docker-compose.yml +++ b/portainer/docker-compose.yml @@ -1,12 +1,17 @@ -version: '3.5' +version: '2.4' services: app: - image: 'portainer/portainer-ce:latest' + image: 'portainer/portainer-ce:2.1.1-alpine' restart: 'always' - labels: - - 'com.centurylinklabs.watchtower.enable=true' + healthcheck: + test: 'curl -f localhost:9000 || exit 1' + interval: '1m' + timeout: '10s' + retries: 3 + start_period: '10s' + networks: - 'nginx' ports: @@ -17,8 +22,7 @@ services: networks: nginx: - external: - name: 'nginx' + external: true volumes: data: diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..7190a60 --- /dev/null +++ b/renovate.json @@ -0,0 +1,3 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json" +} diff --git a/tshock/.env.example b/tshock/.env.example index fea30eb..0a562b3 100644 --- a/tshock/.env.example +++ b/tshock/.env.example @@ -1,29 +1,15 @@ -# 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 . - - -# Build arguments +# What version of TShock to use RELEASE_TAG= -# Environment variables +# What world size to create: +# 1 for small, 2 for medium, 3 for large AUTOCREATE=2 -# Mount points -CONFIG_DIR= -LOGS_DIR= -WORLDS_DIR= +# Mount points for the data directories +# By default, it creates volumes +CONFIG_DIR=config +LOGS_DIR=logs +WORLDS_DIR=worlds -# Other +# The port to publish the server on PORT=7777 diff --git a/tshock/Dockerfile b/tshock/Dockerfile index 2c694c1..c9f2d50 100644 --- a/tshock/Dockerfile +++ b/tshock/Dockerfile @@ -1,49 +1,27 @@ -# 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 . - - -FROM alpine:latest AS base +FROM alpine:3.13.5 AS base # Build arguments ARG RELEASE_TAG -# Add unzip & curl -RUN apk update && apk add --no-cache unzip curl - WORKDIR /terraria -# Download & unzip -# TODO convert this to jq? -RUN curl -s "https://api.github.com/repos/Pryaxis/TShock/releases/tags/${RELEASE_TAG}" | \ -grep "browser_download_url" | \ -grep -o "https[^\"]\+" | \ -xargs curl -sLo tshock.zip && \ -unzip tshock.zip && \ -rm tshock.zip && \ -# Is there a better way to do this? -mv TShock* tshock +RUN apk update && apk add --no-cache unzip curl && \ + curl -s "https://api.github.com/repos/Pryaxis/TShock/releases/tags/${RELEASE_TAG}" | \ + grep "browser_download_url" | \ + grep -o "https[^\"]\+" | \ + xargs curl -sLo tshock.zip && \ + unzip -d tshock tshock.zip && \ + rm tshock.zip -FROM mono:latest +FROM mono:6.12.0.107 WORKDIR /terraria COPY --from=base /terraria/tshock /terraria # Create worlds directory & symlink it RUN mkdir -p worlds logs config /root/.local/share/Terraria && \ -ln -s /terraria/worlds /root/.local/share/Terraria/Worlds + ln -s /terraria/worlds /root/.local/share/Terraria/Worlds ENTRYPOINT \ mono /terraria/TerrariaServer.exe \ diff --git a/tshock/README.md b/tshock/README.md index 4351aa4..8cda9d8 100644 --- a/tshock/README.md +++ b/tshock/README.md @@ -1,23 +1,3 @@ - - - # Build arguments 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 diff --git a/tshock/docker-compose.yml b/tshock/docker-compose.yml index 31ad2a0..32181e7 100644 --- a/tshock/docker-compose.yml +++ b/tshock/docker-compose.yml @@ -1,37 +1,25 @@ -# 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 . - - -version: '3.5' +version: '2.4' services: - tshock: + app: build: context: . args: - 'RELEASE_TAG=${RELEASE_TAG}' - image: 'terraria-tshock:${RELEASE_TAG}' - - restart: 'unless-stopped' + image: 'chewingbever/terraria-tshock:${RELEASE_TAG}' + restart: 'always' stdin_open: true tty: true environment: - - AUTOCREATE + - 'AUTOCREATE' ports: - '$PORT:7777' volumes: - '$CONFIG_DIR:/terraria/config' - '$LOGS_DIR:/terraria/logs' - '$WORLDS_DIR:/terraria/worlds' + +volumes: + config: + logs: + worlds: diff --git a/vim/de b/vim/de index 18f7acf..fb00846 100755 --- a/vim/de +++ b/vim/de @@ -1,2 +1,3 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh + docker run --rm -it -v "$1":/data -w '/data' chewingbever/nvim:latest