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