diff --git a/README.md b/README.md
index 72ab414..6ef5b35 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,24 @@
-# self-hosting
+
+
+
+# self-hosting
# Contents
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.
# 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`).
@@ -28,27 +45,23 @@ 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
new file mode 100644
index 0000000..205abbb
--- /dev/null
+++ b/backups/.gitignore
@@ -0,0 +1,2 @@
+__pycache__/
+backup_tool
diff --git a/backups/README.md b/backups/README.md
new file mode 100644
index 0000000..3edfd50
--- /dev/null
+++ b/backups/README.md
@@ -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.
diff --git a/backups/app/__main__.py b/backups/app/__main__.py
new file mode 100644
index 0000000..535d616
--- /dev/null
+++ b/backups/app/__main__.py
@@ -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()
diff --git a/backups/app/notifier.py b/backups/app/notifier.py
new file mode 100644
index 0000000..e69de29
diff --git a/backups/app/specs/__init__.py b/backups/app/specs/__init__.py
new file mode 100644
index 0000000..5104164
--- /dev/null
+++ b/backups/app/specs/__init__.py
@@ -0,0 +1,2 @@
+from .specs import Spec
+from .parser import parse_specs_file
diff --git a/backups/app/specs/parser.py b/backups/app/specs/parser.py
new file mode 100644
index 0000000..fab362a
--- /dev/null
+++ b/backups/app/specs/parser.py
@@ -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
diff --git a/backups/app/specs/specs.py b/backups/app/specs/specs.py
new file mode 100644
index 0000000..f2971ca
--- /dev/null
+++ b/backups/app/specs/specs.py
@@ -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"]
+ )
diff --git a/backups/backups.yaml.example b/backups/backups.yaml.example
new file mode 100644
index 0000000..68a203b
--- /dev/null
+++ b/backups/backups.yaml.example
@@ -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
diff --git a/backups/install.sh b/backups/install.sh
new file mode 100755
index 0000000..d846c29
--- /dev/null
+++ b/backups/install.sh
@@ -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
diff --git a/firefly/.env.example b/firefly/.env.example
index 58202bb..164c22c 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=firefly
+DB_PASSWORD=password
# 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 7547831..65e501e 100644
--- a/firefly/docker-compose.yml
+++ b/firefly/docker-compose.yml
@@ -1,4 +1,4 @@
-version: '2.4'
+version: '2.8'
services:
app:
@@ -6,23 +6,24 @@ services:
context: '.'
args:
- 'LOCALE=$DEFAULT_LOCALE'
- image: 'chewingbever/firefly-iii-cron:latest'
+ image: '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'
@@ -30,33 +31,35 @@ services:
- 'upload:/var/www/html/storage/upload'
db:
- image: 'postgres:13.2-alpine'
+ image: 'postgres:13-alpine'
restart: 'always'
-
healthcheck:
- test: 'pg_isready -U firefly'
+ test: 'pg_isready -U $DB_USERNAME'
interval: '10s'
timeout: '5s'
retries: 5
- start_period: '0s'
environment:
- - 'POSTGRES_DB=firefly'
- - 'POSTGRES_PASSWORD=firefly'
- - 'POSTGRES_USER=firefly'
+ - 'POSTGRES_DB=$DB_DATABASE'
+ - 'POSTGRES_PASSWORD=$DB_PASSWORD'
+ - 'POSTGRES_USER=$DB_USERNAME'
+ labels:
+ - 'com.centurylinklabs.watchtower.enable=true'
volumes:
- 'db-data:/var/lib/postgresql/data'
redis:
- image: 'redis:6.2.2-alpine'
+ image: 'redis:6-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
deleted file mode 100644
index 95e1324..0000000
--- a/gitea/.env.example
+++ /dev/null
@@ -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
diff --git a/gitea/docker-compose.yml b/gitea/docker-compose.yml
deleted file mode 100644
index 6e65af8..0000000
--- a/gitea/docker-compose.yml
+++ /dev/null
@@ -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:
diff --git a/koel/.env.example b/koel/.env.example
index 9ba0882..d58e408 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=koel
+DB_PASSWORD=changeme
# 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 c207d71..19d6e1a 100644
--- a/koel/docker-compose.yml
+++ b/koel/docker-compose.yml
@@ -1,22 +1,14 @@
-version: '2.4'
+version: '3.5'
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:
- # Haven't found a good MySQL healthcheck yet
- condition: 'service_started'
-
+ - 'db'
+ labels:
+ - 'com.centurylinklabs.watchtower.enable=true'
networks:
- 'default'
- 'nginx'
@@ -24,18 +16,19 @@ services:
- './.env:/var/www/html/.env'
- 'covers:/var/www/html/public/img/covers'
- 'music:/music'
- - 'index:/var/www/html/storage/search-indexes'
db:
- image: 'mariadb:10.5.9-focal'
+ image: 'mysql:8'
restart: 'always'
command: '--default-authentication-plugin=mysql_native_password'
environment:
- 'MYSQL_DATABASE=koel'
- - 'MYSQL_USER=koel'
- - 'MYSQL_PASSWORD=koel'
- - 'MYSQL_RANDOM_ROOT_PASSWORD=yes'
+ - 'MYSQL_PASSWORD=$DB_PASSWORD'
+ - 'MYSQL_ROOT_PASSWORD=$DB_PASSWORD'
+ - 'MYSQL_USER=$DB_USERNAME'
+ labels:
+ - 'com.centurylinklabs.watchtower.enable=true'
volumes:
- 'db-data:/var/lib/mysql'
@@ -46,5 +39,4 @@ networks:
volumes:
covers:
db-data:
- index:
music:
diff --git a/minecraft/fabric/docker-compose.yml b/minecraft/fabric/docker-compose.yml
index 440ad2b..28d43bf 100644
--- a/minecraft/fabric/docker-compose.yml
+++ b/minecraft/fabric/docker-compose.yml
@@ -1,4 +1,4 @@
-version: '2.0'
+version: '3.5'
services:
app:
build:
diff --git a/minecraft/forge/docker-compose.yml b/minecraft/forge/docker-compose.yml
index 95ba6e4..f8077d2 100644
--- a/minecraft/forge/docker-compose.yml
+++ b/minecraft/forge/docker-compose.yml
@@ -1,4 +1,4 @@
-version: '2.0'
+version: '3.5'
services:
app:
build:
diff --git a/minecraft/papermc/docker-compose.yml b/minecraft/papermc/docker-compose.yml
index c9a41bc..fd4afec 100644
--- a/minecraft/papermc/docker-compose.yml
+++ b/minecraft/papermc/docker-compose.yml
@@ -1,4 +1,4 @@
-version: '2.0'
+version: '3.5'
services:
app:
build:
@@ -7,7 +7,7 @@ services:
- 'BASE_IMAGE'
- 'MC_VERSION'
- 'PAPERMC_VERSION'
- image: 'localhost:5000/mc-papermc:${MC_VERSION}-${PAPERMC_VERSION}'
+ image: 'chewingbever/mc-papermc:${MC_VERSION}-${PAPERMC_VERSION}'
restart: 'always'
# Needed to interact with server console
diff --git a/miniflux/db.env.example b/miniflux/db.env.example
new file mode 100644
index 0000000..79ebaff
--- /dev/null
+++ b/miniflux/db.env.example
@@ -0,0 +1,3 @@
+POSTGRES_DB=miniflux
+POSTGRES_USER=miniflux
+POSTGRES_PASSWORD=changeme
diff --git a/miniflux/docker-compose.yml b/miniflux/docker-compose.yml
index 24aae5a..4a59057 100644
--- a/miniflux/docker-compose.yml
+++ b/miniflux/docker-compose.yml
@@ -1,44 +1,28 @@
-version: '2.4'
+version: '3.5'
services:
app:
- image: 'miniflux/miniflux:2.0.29'
+ image: 'miniflux/miniflux:latest'
restart: 'always'
depends_on:
- 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'
-
+ - 'db'
env_file:
- - '.env'
- environment:
- # This is always the same, so we just put it here
- - 'DATABASE_URL=postgres://miniflux:miniflux@db/miniflux?sslmode=disable'
+ - 'miniflux.env'
+ labels:
+ - 'com.centurylinklabs.watchtower.enable=true'
networks:
- 'default'
- 'nginx'
db:
- image: 'postgres:13.2-alpine'
+ image: 'postgres:13-alpine'
restart: 'always'
- 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'
+ env_file:
+ - 'db.env'
+ labels:
+ - 'com.centurylinklabs.watchtower.enable=true'
volumes:
- 'db-data:/var/lib/postgresql/data'
diff --git a/miniflux/.env.example b/miniflux/miniflux.env.example
similarity index 63%
rename from miniflux/.env.example
rename to miniflux/miniflux.env.example
index 0a429a9..161f6c8 100644
--- a/miniflux/.env.example
+++ b/miniflux/miniflux.env.example
@@ -1,4 +1,5 @@
# Database settings
+DATABASE_URL=postgres://miniflux:changeme@db/miniflux?sslmode=disable
RUN_MIGRATIONS=1
# Auto-create admin user
diff --git a/monica/.env.example b/monica/.env.example
deleted file mode 100644
index 27ad3e7..0000000
--- a/monica/.env.example
+++ /dev/null
@@ -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=
diff --git a/monica/docker-compose.yml b/monica/docker-compose.yml
deleted file mode 100644
index 2556e8e..0000000
--- a/monica/docker-compose.yml
+++ /dev/null
@@ -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:
diff --git a/nextcloud/.env.example b/nextcloud/.env.example
index 2c43195..526887b 100644
--- a/nextcloud/.env.example
+++ b/nextcloud/.env.example
@@ -2,7 +2,7 @@
POSTGRES_HOST=db
POSTGRES_DB=nextcloud
POSTGRES_USER=nextcloud
-POSTGRES_PASSWORD=nextcloud
+POSTGRES_PASSWORD=pass
# Redis
REDIS_HOST=redis
diff --git a/nextcloud/docker-compose.yml b/nextcloud/docker-compose.yml
index bb6be0d..b287465 100644
--- a/nextcloud/docker-compose.yml
+++ b/nextcloud/docker-compose.yml
@@ -1,24 +1,17 @@
-version: '2.4'
+version: '3.5'
services:
app:
- image: 'nextcloud:21.0.1-apache'
+ image: 'nextcloud:20-apache'
restart: 'always'
- healthcheck:
- test: 'curl -f localhost || exit 1'
- interval: '1m'
- timeout: '10s'
- retries: 3
- start_period: '10s'
depends_on:
- db:
- condition: 'service_healthy'
- redis:
- condition: 'service_healthy'
-
+ - 'db'
+ - 'redis'
env_file:
- '.env'
+ labels:
+ - 'com.centurylinklabs.watchtower.enable=true'
networks:
- 'default'
- 'nginx'
@@ -28,41 +21,40 @@ services:
- 'root:/var/www/html'
cron:
- image: 'nextcloud:21.0.1-apache'
- restart: 'always'
+ image: 'nextcloud:20-apache'
entrypoint: '/cron.sh'
+ restart: 'always'
depends_on:
- app:
- condition: 'service_healthy'
-
+ - 'app'
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.2-alpine'
+ image: 'postgres:13-alpine'
restart: 'always'
environment:
- - 'POSTGRES_DB=nextcloud'
- - 'POSTGRES_USER=nextcloud'
- - 'POSTGRES_PASSWORD=nextcloud'
+ - 'POSTGRES_DB'
+ - 'POSTGRES_USER'
+ - 'POSTGRES_PASSWORD'
+ labels:
+ - 'com.centurylinklabs.watchtower.enable=true'
volumes:
- 'db-data:/var/lib/postgresql/data'
redis:
- image: 'redis:6.2.2-alpine'
+ image: 'redis:6-alpine'
restart: 'always'
- healthcheck:
- test: 'redis-cli -h localhost ping'
- interval: '10s'
- timeout: '5s'
- retries: 3
+ labels:
+ - 'com.centurylinklabs.watchtower.enable=true'
networks:
nginx:
diff --git a/nginx/.env.example b/nginx/.env.example
index d63211e..445e483 100644
--- a/nginx/.env.example
+++ b/nginx/.env.example
@@ -1,65 +1,12 @@
-# =====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
+# Main domain; also name of certificate
+MAIN_DOMAIN=
+
+# Comma-separated list of other domains which also arrive here
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
new file mode 100644
index 0000000..309ea38
--- /dev/null
+++ b/nginx/build/Dockerfile
@@ -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" ]
diff --git a/nginx/build/entrypoint.sh b/nginx/build/entrypoint.sh
new file mode 100644
index 0000000..d652550
--- /dev/null
+++ b/nginx/build/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;"
diff --git a/nginx/build/renew b/nginx/build/renew
new file mode 100644
index 0000000..98327d4
--- /dev/null
+++ b/nginx/build/renew
@@ -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"
diff --git a/nginx/docker-compose.yml b/nginx/docker-compose.yml
index f991d1b..c8e51f1 100644
--- a/nginx/docker-compose.yml
+++ b/nginx/docker-compose.yml
@@ -1,13 +1,15 @@
-version: '2.4'
-
+version: '3.5'
services:
app:
- build: './nginx'
+ build: './build'
image: 'nginx-certbot:stable-alpine'
- restart: 'always'
- env_file:
- - '.env'
+ environment:
+ - 'DOMAINS'
+ - 'EMAIL'
+ - 'HTTPS_PORT'
+ - 'HTTP_PORT'
+ - 'MAIN_DOMAIN'
networks:
- 'nginx'
ports:
diff --git a/nginx/nginx.conf b/nginx/nginx.conf
index c3e3167..6f321f0 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/*.conf;
+include conf.d/*;
diff --git a/nginx/nginx/Dockerfile b/nginx/nginx/Dockerfile
deleted file mode 100644
index 19a359b..0000000
--- a/nginx/nginx/Dockerfile
+++ /dev/null
@@ -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" ]
diff --git a/nginx/nginx/entrypoint.sh b/nginx/nginx/entrypoint.sh
deleted file mode 100755
index 1205a79..0000000
--- a/nginx/nginx/entrypoint.sh
+++ /dev/null
@@ -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;"
diff --git a/nginx/nginx/renew b/nginx/nginx/renew
deleted file mode 100755
index bdbebcf..0000000
--- a/nginx/nginx/renew
+++ /dev/null
@@ -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"
diff --git a/nginx/sites-available/firefly-iii.conf.template b/nginx/sites-available/firefly-iii.conf
similarity index 60%
rename from nginx/sites-available/firefly-iii.conf.template
rename to nginx/sites-available/firefly-iii.conf
index e9447fc..1a9f1c4 100644
--- a/nginx/sites-available/firefly-iii.conf.template
+++ b/nginx/sites-available/firefly-iii.conf
@@ -1,11 +1,6 @@
server {
- # 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};
+ listen 443 ssl;
+ server_name DOMAIN;
location / {
proxy_set_header Host $host;
@@ -18,7 +13,7 @@ server {
proxy_set_header Connection "upgrade";
resolver 127.0.0.11;
- proxy_pass http://${FIREFLY_HOST}:8080;
+ proxy_pass http://firefly_app_1:8080;
}
}
diff --git a/nginx/sites-available/gitea.conf.template b/nginx/sites-available/gitea.conf.template
deleted file mode 100644
index 477f4be..0000000
--- a/nginx/sites-available/gitea.conf.template
+++ /dev/null
@@ -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;
- }
- }
-}
-
diff --git a/nginx/sites-available/koel.conf b/nginx/sites-available/koel.conf
new file mode 100644
index 0000000..82832a5
--- /dev/null
+++ b/nginx/sites-available/koel.conf
@@ -0,0 +1,9 @@
+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
deleted file mode 100644
index 93f4fc5..0000000
--- a/nginx/sites-available/koel.conf.template
+++ /dev/null
@@ -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;
- }
-}
diff --git a/nginx/sites-available/miniflux.conf b/nginx/sites-available/miniflux.conf
new file mode 100644
index 0000000..da25654
--- /dev/null
+++ b/nginx/sites-available/miniflux.conf
@@ -0,0 +1,10 @@
+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
deleted file mode 100644
index eefbe26..0000000
--- a/nginx/sites-available/miniflux.conf.template
+++ /dev/null
@@ -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;
- }
-}
-
diff --git a/nginx/sites-available/monica.conf.template b/nginx/sites-available/monica.conf.template
deleted file mode 100644
index 05e5803..0000000
--- a/nginx/sites-available/monica.conf.template
+++ /dev/null
@@ -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;
- }
-}
diff --git a/nginx/sites-available/nefarious.conf.template b/nginx/sites-available/nefarious.conf
similarity index 100%
rename from nginx/sites-available/nefarious.conf.template
rename to nginx/sites-available/nefarious.conf
diff --git a/nginx/sites-available/nextcloud.conf.template b/nginx/sites-available/nextcloud.conf
similarity index 84%
rename from nginx/sites-available/nextcloud.conf.template
rename to nginx/sites-available/nextcloud.conf
index 9ade02e..e36549d 100644
--- a/nginx/sites-available/nextcloud.conf.template
+++ b/nginx/sites-available/nextcloud.conf
@@ -1,12 +1,7 @@
server {
- # 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};
+ listen 443 ssl;
+ listen [::]:443 ssl http2;
+ server_name DOMAIN;
# Enable gzip but do not remove ETag headers
gzip on;
@@ -28,7 +23,7 @@ server {
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
- proxy_pass http://${NEXTCLOUD_HOST}:80/;
+ proxy_pass http://nextcloud_app_1:80/;
proxy_pass_request_headers on;
diff --git a/nginx/sites-available/podgrab.conf.template b/nginx/sites-available/podgrab.conf.template
deleted file mode 100644
index 81ef710..0000000
--- a/nginx/sites-available/podgrab.conf.template
+++ /dev/null
@@ -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/;
- }
-}
-
diff --git a/nginx/sites-available/portainer.conf b/nginx/sites-available/portainer.conf
new file mode 100644
index 0000000..98b1e44
--- /dev/null
+++ b/nginx/sites-available/portainer.conf
@@ -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;
+ }
+}
diff --git a/nginx/sites-available/portainer.conf.template b/nginx/sites-available/portainer.conf.template
deleted file mode 100644
index c9ec72c..0000000
--- a/nginx/sites-available/portainer.conf.template
+++ /dev/null
@@ -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;
- }
-}
diff --git a/nginx/templates/http.conf.template b/nginx/templates/http.conf.template
index bd928c6..2b62f29 100644
--- a/nginx/templates/http.conf.template
+++ b/nginx/templates/http.conf.template
@@ -1,5 +1,9 @@
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
ssl_protocols TLSv1.2;
@@ -25,6 +29,7 @@ http {
return 301 https://$host:${HTTPS_PORT}$request_uri;
}
+
# LOAD SITES
- include conf.d/sites-enabled/*.conf;
+ include sites-enabled/*.conf;
}
diff --git a/nginx/templates/sites-enabled/.gitignore b/nginx/templates/sites-enabled/.gitignore
deleted file mode 100644
index cec9082..0000000
--- a/nginx/templates/sites-enabled/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-*
-
-!.gitignore
diff --git a/podgrab/.env.example b/podgrab/.env.example
deleted file mode 100644
index 6c69f28..0000000
--- a/podgrab/.env.example
+++ /dev/null
@@ -1,5 +0,0 @@
-# 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
deleted file mode 100644
index 47e3707..0000000
--- a/podgrab/docker-compose.yml
+++ /dev/null
@@ -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:
diff --git a/portainer/docker-compose.yml b/portainer/docker-compose.yml
index 88165b0..31b62b3 100644
--- a/portainer/docker-compose.yml
+++ b/portainer/docker-compose.yml
@@ -1,17 +1,12 @@
-version: '2.4'
+version: '3.5'
services:
app:
- image: 'portainer/portainer-ce:2.1.1-alpine'
+ image: 'portainer/portainer-ce:latest'
restart: 'always'
- healthcheck:
- test: 'curl -f localhost:9000 || exit 1'
- interval: '1m'
- timeout: '10s'
- retries: 3
- start_period: '10s'
-
+ labels:
+ - 'com.centurylinklabs.watchtower.enable=true'
networks:
- 'nginx'
ports:
@@ -22,7 +17,8 @@ services:
networks:
nginx:
- external: true
+ external:
+ name: 'nginx'
volumes:
data:
diff --git a/renovate.json b/renovate.json
deleted file mode 100644
index 7190a60..0000000
--- a/renovate.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "$schema": "https://docs.renovatebot.com/renovate-schema.json"
-}
diff --git a/tshock/.env.example b/tshock/.env.example
index 0a562b3..fea30eb 100644
--- a/tshock/.env.example
+++ b/tshock/.env.example
@@ -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 .
+
+
+# Build arguments
RELEASE_TAG=
-# What world size to create:
-# 1 for small, 2 for medium, 3 for large
+# Environment variables
AUTOCREATE=2
-# Mount points for the data directories
-# By default, it creates volumes
-CONFIG_DIR=config
-LOGS_DIR=logs
-WORLDS_DIR=worlds
+# Mount points
+CONFIG_DIR=
+LOGS_DIR=
+WORLDS_DIR=
-# The port to publish the server on
+# Other
PORT=7777
diff --git a/tshock/Dockerfile b/tshock/Dockerfile
index c9f2d50..2c694c1 100644
--- a/tshock/Dockerfile
+++ b/tshock/Dockerfile
@@ -1,27 +1,49 @@
-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 .
+
+
+FROM alpine:latest AS base
# Build arguments
ARG RELEASE_TAG
+# Add unzip & curl
+RUN apk update && apk add --no-cache unzip curl
+
WORKDIR /terraria
-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
+# 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
-FROM mono:6.12.0.107
+FROM mono:latest
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 8cda9d8..4351aa4 100644
--- a/tshock/README.md
+++ b/tshock/README.md
@@ -1,3 +1,23 @@
+
+
+
# 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 32181e7..31ad2a0 100644
--- a/tshock/docker-compose.yml
+++ b/tshock/docker-compose.yml
@@ -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 .
+
+
+version: '3.5'
services:
- app:
+ tshock:
build:
context: .
args:
- 'RELEASE_TAG=${RELEASE_TAG}'
- image: 'chewingbever/terraria-tshock:${RELEASE_TAG}'
- restart: 'always'
+ image: 'terraria-tshock:${RELEASE_TAG}'
+
+ restart: 'unless-stopped'
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 fb00846..18f7acf 100755
--- a/vim/de
+++ b/vim/de
@@ -1,3 +1,2 @@
-#!/usr/bin/env sh
-
+#!/usr/bin/env bash
docker run --rm -it -v "$1":/data -w '/data' chewingbever/nvim:latest