├── .gitignore ├── README.md ├── _utilities ├── bitwarden.svg.png ├── borg.svg ├── docker.png ├── element.png ├── fail2ban.png ├── freshrss.png ├── gotify.png ├── httpd.png ├── jellyfin.png ├── matrix.png ├── nextcloud.png ├── nextcloud_instruction.png ├── pihole.svg.png ├── seafile.png ├── traefik.logo.png ├── transmission.png ├── trilium.png ├── unbound.svg ├── watchtower.png ├── wireguard.png └── wordpress.png ├── borg-backup ├── .env ├── README.md ├── backup-borg-s3.sh ├── download-backup-s3.sh └── excludes.txt ├── fail2ban ├── .env ├── README.md ├── data │ ├── action.d │ │ ├── nftables-forward.conf │ │ └── nftables-input.conf │ ├── filter.d │ │ ├── bitwarden-admin.conf │ │ └── bitwarden-auth.conf │ └── jail.d │ │ ├── bitwarden-admin.conf │ │ ├── bitwarden-auth.conf │ │ └── sshd.conf └── docker-compose.yml ├── freshrss ├── .env ├── README.md └── docker-compose.yml ├── gotify ├── .env ├── README.md └── docker-compose.yml ├── jellyfin ├── .env ├── README.md └── docker-compose.yml ├── nextcloud ├── .env ├── README.md └── docker-compose.yml ├── seafile ├── .env ├── README.md └── docker-compose.yml ├── synapse-element ├── .env ├── README.md ├── docker-compose.yml └── element-web │ └── config.json ├── traefik ├── .env ├── README.md ├── docker-compose.yml ├── rules │ ├── tls.yml │ └── whitelist.yml └── traefik.yml ├── transmission ├── .env ├── README.md └── docker-compose.yml ├── trilium ├── .env ├── README.md └── docker-compose.yml ├── vaultwarden ├── .env ├── README.md └── docker-compose.yml ├── watchtower ├── .env ├── README.md └── docker-compose.yml ├── webserver ├── .env ├── README.md ├── data │ └── index.html └── docker-compose.yml ├── wireguard-pihole-unbound ├── .env ├── README.md ├── docker-compose.yml └── unbound │ └── unbound.conf └── wordpress ├── .env ├── README.md ├── data └── wp-config.php └── docker-compose.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | docker 3 |

4 | 5 | Guide with examples ! 6 | 7 | # Services 8 | 9 | * [traefik](traefik/) - reverse proxy and SSL manager 10 | * [borg-backup](borg-backup/) - backup scripts (local and AWS) 11 | * [fail2ban](fail2ban/) - security tool (ban IP) 12 | * [freshrss](freshrss/) - RSS feed aggregator 13 | * [gotify](gotify/) - notification service 14 | * [jellyfin](jellyfin/) - media System 15 | * [nextcloud](nextcloud/) - file-hosting software system 16 | * [seafile](seafile/) - file-hosting software system 17 | * [synapse-element](synapse-element/) - decentralised communication system 18 | * [transmission](transmission/) - fast, easy, and free BitTorrent client 19 | * [trilium](trilium/) - hierarchical note-taking application 20 | * [vaultwarden](vaultwarden/) - password manager 21 | * [watchtower](watchtower/) - automatic docker images update 22 | * [webserver](webserver/) - simple apache webserver 23 | * [wireguard-pihole-unbound](wireguard-pihole-unbound/) - combination of WireGuard, PiHole, and Unbound 24 | * [wordpress](wordpress/) - blogging tool with a content management system (CMS) 25 | 26 | 27 | # Information 28 | 29 | The overall guide is centered around example. Each of the services is tied with either a docker-compose or a script, everything has been made so that each service is almost ready to use, only a few user-specific variable are required. 30 | 31 | All services respect a certain format : 32 | 33 | - **About** - basic overview of the service 34 | - **Table of Contents** 35 | - **Files structure** - lists all the files and folder required 36 | - **Information** - detailed information about the service and the example 37 | - **Usage** - required configuration and commands to use the service 38 | - **Update** - how to update the container, most of the time it is using watchtower 39 | - **Backup** - how to back up the container, most of the time it is using borg-backup 40 | 41 | Traefik is the core of this setup as it is the reverse proxy, it should be one of the first services to configure and use. 42 | 43 | # Requirement 44 | 45 | Basic linux knowledge is required and docker is a must-have, everything should be pretty easy to set up but understanding docker will make it even more easy. 46 | Each guide gives links to the official documentation, they are usually well written, and they should answer most of your questions. 47 | 48 | On the technical side : 49 | 50 | * docker and docker-compose (1.X) are required, the installation process is fairly easy. 51 | * a domain, some can be found for free but most are usually pretty cheap. 52 | 53 | # Usage 54 | 55 | All the docker-compose provided in this repository are ready to be used, and you should not have to touch them. The only thing you need to change are the `.env` file provided with the docker-compose, they are user-specific. 56 | 57 | To begin with, you can clone this repository on your host. 58 | 59 | ```bash 60 | git clone https://github.com/BaptisteBdn/docker-selfhosted-apps.git 61 | ``` 62 | 63 | Provided you already have a domain, you can use the following commands to update all `.env` at once as well as some specific config files. 64 | 65 | ```bash 66 | DOMAIN=your-domain.com 67 | find ./ \( -name ".env" -or -name "*.yml" -or -name "*.json" \) -type f -exec sed -i 's/example.com/'$DOMAIN'/g' {} \; 68 | ``` 69 | 70 | You can now go forward and try whatever service you want, every example as a `# Usage` section to guide you through the process. However, as most of them are using Traefik, it is recommended to set this one first. 71 | 72 | # Other 73 | 74 | ## Docker and UFW 75 | 76 | UFW is a popular iptables front end on Ubuntu that makes it easy to manage firewall rules. But when Docker is installed, Docker bypass the UFW rules and the published ports can be accessed from outside. 77 | 78 | An [easy fix](https://github.com/chaifeng/ufw-docker) is available, allowing to easily manage your firewall. As most of the services are going through Traefik, only the port 443 is mandatory. If another port is required, it will be listed in the requirements. 79 | 80 | ## Docker tips 81 | 82 | * Get shell access whilst the container is running 83 | ``` 84 | docker exec -it container-name /bin/bash 85 | ``` 86 | * Monitor the logs of the container in realtime 87 | ``` 88 | docker logs -f container-name 89 | ``` 90 | 91 | ## Docker images 92 | 93 | Most images are used with the tag `latest` as it simplify the testing. It is usually not recommended running an image with this tag as it is not very dynamic and precise. 94 | Feel free to experiment with the provided docker-compose examples and then use a better versionning system. For more information about [latest](https://vsupalov.com/docker-latest-tag/). 95 | 96 | ## Updating docker images 97 | 98 | This repository images are automatically updated with watchtower, however this can be a security risk. More details in the [watchtower guide](watchtower). 99 | 100 | If you want to manually update an image, you can use docker-compose. 101 | 102 | * Update all images for a specific docker-compose file 103 | ``` 104 | sudo docker-compose pull 105 | ``` 106 | * Update a single image 107 | ``` 108 | sudo docker-compose pull image-name 109 | ``` 110 | * Recreate all updated containers with docker-compose 111 | ``` 112 | sudo docker-compose up -d 113 | ``` 114 | * Recreate a single container with docker-compose 115 | ``` 116 | sudo docker-compose up -d container-name 117 | ``` 118 | * Remove all dangling and unused images 119 | ``` 120 | sudo docker image prune -a 121 | ``` 122 | 123 | ## Docker tools 124 | 125 | Some useful tools to manage your private docker infrastructure. 126 | 127 | - [lazydocker](https://github.com/jesseduffield/lazydocker) - A simple terminal UI for both docker and docker-compose, written in Go with the gocui library. By @jesseduffield 128 | - [dive](https://github.com/wagoodman/dive) - A tool for exploring each layer in a docker image. By @anchore. 129 | - [grype](https://github.com/anchore/grype) - A vulnerability scanner for container images and filesystems. By @anchore. 130 | 131 | ## Docker resources 132 | 133 | A compilation of resources mainly focus on security. 134 | 135 | - [CIS Docker 1.13.0 Benchmark](https://downloads.cisecurity.org/#/) - provides prescriptive guidance for establishing a secure configuration posture for Docker 136 | - [Docker security](https://docs.docker.com/engine/security/) - official docker documentation about security 137 | - [Docker security OWASP](https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html) - OWASP security cheat sheet 138 | 139 | # Credits 140 | 141 | This guide is inspired from [@DoTheEvo](https://github.com/DoTheEvo/selfhosted-apps-docker) own docker guide, built with caddy at its core, check it out ! 142 | -------------------------------------------------------------------------------- /_utilities/bitwarden.svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/bitwarden.svg.png -------------------------------------------------------------------------------- /_utilities/borg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /_utilities/docker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/docker.png -------------------------------------------------------------------------------- /_utilities/element.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/element.png -------------------------------------------------------------------------------- /_utilities/fail2ban.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/fail2ban.png -------------------------------------------------------------------------------- /_utilities/freshrss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/freshrss.png -------------------------------------------------------------------------------- /_utilities/gotify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/gotify.png -------------------------------------------------------------------------------- /_utilities/httpd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/httpd.png -------------------------------------------------------------------------------- /_utilities/jellyfin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/jellyfin.png -------------------------------------------------------------------------------- /_utilities/matrix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/matrix.png -------------------------------------------------------------------------------- /_utilities/nextcloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/nextcloud.png -------------------------------------------------------------------------------- /_utilities/nextcloud_instruction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/nextcloud_instruction.png -------------------------------------------------------------------------------- /_utilities/pihole.svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/pihole.svg.png -------------------------------------------------------------------------------- /_utilities/seafile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/seafile.png -------------------------------------------------------------------------------- /_utilities/traefik.logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/traefik.logo.png -------------------------------------------------------------------------------- /_utilities/transmission.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/transmission.png -------------------------------------------------------------------------------- /_utilities/trilium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/trilium.png -------------------------------------------------------------------------------- /_utilities/unbound.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /_utilities/watchtower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/watchtower.png -------------------------------------------------------------------------------- /_utilities/wireguard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/wireguard.png -------------------------------------------------------------------------------- /_utilities/wordpress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/_utilities/wordpress.png -------------------------------------------------------------------------------- /borg-backup/.env: -------------------------------------------------------------------------------- 1 | # Directory to back up 2 | DOCKER_DIR=/path/to/docker_directory 3 | 4 | # Borg repository 5 | BORG_REPO=/path/to/borg_repository 6 | BORG_PASSPHRASE=borg_passphrase 7 | 8 | # AWS configuration 9 | BORG_S3_BACKUP_BUCKET=bucket_name 10 | BORG_S3_BACKUP_AWS_PROFILE=aws_backup_profile 11 | 12 | # Gotify url and token (optional) 13 | GOTIFY_URL=https://gotify.example.com 14 | GOTIFY_TOKEN=gotify_token 15 | 16 | # Threshold (in GB) to limit the amount of data synced to AWS (optional) 17 | # If the borg repository is above the threshold, backup will not be saved to AWS 18 | # 0 for unlimited 19 | BACKUP_THRESHOLD=50 -------------------------------------------------------------------------------- /borg-backup/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | Borg 5 |

6 | 7 | BorgBackup is a deduplicating backup program, it supports compression and authenticated encryption. 8 | 9 | * [Github](https://github.com/borgbackup/borg) 10 | * [Documentation](https://borgbackup.readthedocs.io/en/stable/) 11 | 12 | Borg is a key element for this selfhosted infrastructure as it will back up all your valuable data, the scripts alongside borg provides the following features : 13 | 14 | - Local backup of your docker repository 15 | - docker-compose, env files, etc. 16 | - **volumes** containing important data for your containers 17 | - External cloud backup on AWS (S3) 18 | - Backup notifications with [Gotify](../gotify) 19 | 20 | The scripts are a modified version of [luispabon/borg-s3-home-backup](https://github.com/luispabon/borg-s3-home-backup). 21 | 22 | # Table of Contents 23 | 24 | 25 | 26 | - [About](#about) 27 | - [Table of Contents](#table-of-contents) 28 | - [Files structure](#files-structure) 29 | - [Information](#information) 30 | - [env](#env) 31 | - [borg](#borg) 32 | - [aws](#aws) 33 | - [Gotify](#gotify) 34 | - [Backup scripts](#backup-scripts) 35 | - [Usage](#usage) 36 | - [Requirements](#requirements) 37 | - [Configuration](#configuration) 38 | - [Download and extract backups](#download-and-extract-backups) 39 | - [Security](#security) 40 | 41 | 42 | 43 | # Files structure 44 | 45 | ```bash 46 | . 47 | |-- .env 48 | |-- backup-borg-s3.sh* 49 | |-- download-backup-s3.sh* 50 | `-- excludes.txt 51 | ``` 52 | - `.env` - a file containing all the environment variables used in backup scripts 53 | - `backup-borg-s3.sh`- a script to back up your data : locally and in the cloud (AWS S3) 54 | - `download-backup-s3.sh`- a script to download your data from the cloud 55 | - `excludes.txt` - an exclude file, default will back up all your docker infrastructure 56 | 57 | Please make sure that all the files and directories are present. 58 | 59 | # Information 60 | 61 | Borg requires user's specific configuration. 62 | 63 | ## .env 64 | Links to the following [.env](.env). 65 | 66 | ### borg 67 | 68 | ```bash 69 | # Directory to back up 70 | DOCKER_DIR=/path/to/docker_directory 71 | ``` 72 | The directory containing all the configuration of the docker containers, usually the directory you cloned this guide into. 73 | 74 | 75 | ```bash 76 | # Borg repository 77 | BORG_REPO=/path/to/borg_repository 78 | BORG_PASSPHRASE=borg_passphrase 79 | ``` 80 | The borg repository where the backups will be located, and the corresponding passphrase used to encrypt the datas. 81 | 82 | To create the repository and set your passphrase : 83 | 84 | ```bash 85 | borg init --encryption=repokey /path/to/repo 86 | ``` 87 | 88 | > You can use [vaultwarden](../vaultwarden) to store your passphrase securly. 89 | 90 | ### aws 91 | 92 | > Keep in mind that AWS S3 is not free. Currently, with approximatly 50 GB of data it costs me around $1 per month. 93 | 94 | ```bash 95 | # AWS configuration 96 | BORG_S3_BACKUP_BUCKET=bucket_name 97 | BORG_S3_BACKUP_AWS_PROFILE=aws_backup_profile 98 | ``` 99 | 100 | AWS provides a lot of services, we are gonna use S3 : Amazon Simple Storage Service (Amazon S3) is an object storage service where you can store and protect any amount of data for virtually any use case. 101 | It is a great, reliable and cheap way to store your already encrypted backups. 102 | 103 | In order to use S3, you will need an AWS account. If you do not have one, I suggest following the [AWS startup guide](https://aws.amazon.com/getting-started/guides/setup-environment/), only the first 3 modules are important. 104 | 105 | Within your AWS account, create another user within IAM, if you followed the guide you should already have created one, I recommend creating a unique user for the backup. 106 | 107 | Next, create your S3 bucket, keep in mind that the name of the bucket must be unique between all users using S3, you can choose something like `aws-docker-selfhosted-backups-8888`. Please be careful not to put your bucket publicly visible, by default it should not be. 108 | 109 | Then, go to IAM, select your backup user and choose `Add permissions` then `Attach existing policies` and then `Create policy`. On the editor, choose JSON and set the following policy for your backup user while changing with the name of the bucket you just created. 110 | 111 | `S3-full-access-backup-bucket` 112 | ```json 113 | { 114 | "Version": "2012-10-17", 115 | "Statement": [ 116 | { 117 | "Sid": "AllAccess", 118 | "Action": "s3:*", 119 | "Effect": "Allow", 120 | "Resource": [ 121 | "arn:aws:s3:::name-of-your-bucket", 122 | "arn:aws:s3:::name-of-your-bucket/*" 123 | ] 124 | } 125 | ] 126 | } 127 | ``` 128 | 129 | Once this is done, add it to your user, this will give full access to the bucket you created to your backup user. 130 | 131 | Now everything is configured within your AWS account, the last step is to configure the profile on your docker host. This step is explained in the module 3 in the [AWS startup guide](https://aws.amazon.com/getting-started/guides/setup-environment/). 132 | 133 | > NOTE: Content inside docker volumes can be sometimes owned by root as they are created by docker, as a result, to avoid conflict I run the backups and AWS upload as root. If you want to do the same, the AWS profile will have to be configured inside root's home. 134 | 135 | The AWS configuration is finished, add the bucket name and the name of your aws profile to the `.env` file. 136 | 137 | To check that everything is set up correctly, use the following command (as root if you plan to run the backup as root): 138 | 139 | ```bash 140 | aws s3 ls --profile=your-profile-name --summarize --recursive s3://name-of-your-bucket 141 | ``` 142 | 143 | The response should be empty, but you should not have any error. 144 | 145 | ### Gotify 146 | 147 | You need to have a selfhosted [gotify](../gotify) available, check the guide if you want to know how to generate a token. 148 | 149 | ## Backup scripts 150 | 151 | The backup script works in 5 steps : 152 | 153 | - Stops all running docker container to ensure uncorrupted files 154 | - Create local borg backup 155 | - Prune old backups 156 | - Keep the most up to date daily, weekly and monthly backup 157 | - Synchronise the local backup to the AWS bucket (kind of like rsync would do) 158 | - Starts all docker containers 159 | - Notify using Gotify 160 | 161 | 162 | The download script works in 2 steps : 163 | 164 | - Check that you have enough space on your host 165 | - Download the remote encrypted backup 166 | 167 | 168 | # Usage 169 | 170 | ## Requirements 171 | 172 | Please ensure that the `.env` is correctly configure. 173 | 174 | ## Configuration 175 | 176 | While you want to keep most of the data, you may also want to exclude heavy files from backups (media files, logs, etc.). 177 | Add any **full path** to any directory or file that you want to exclude to `exclude.txt`. 178 | 179 | > Default will back up EVERYTHING. I also recommend setting the BACKUP_THRESHOLD value in the `.env` as it will prevent any AWS upload if the backup is larger than the setting. 180 | 181 | Now that everything is set up, you can run the backup script. 182 | 183 | ```bash 184 | sudo /bin/bash /path/to/backup-borg-s3.sh 185 | ``` 186 | 187 | You can also use cron to automate the backup. 188 | 189 | ```bash 190 | 1 3 * * 1 root /bin/bash /path/to/backup-borg-s3.sh >> /var/log/backup.log 191 | ``` 192 | This will run the backup script as root every monday at 3. 193 | 194 | ## Download and extract backups 195 | 196 | If you ever need your backup, borg makes it pretty easy. 197 | 198 | First, download the backup using the download backup script, you will need the `.env` with only the AWS settings (aws bucket name and AWS profile name). 199 | 200 | ```bash 201 | /bin/bash /download-backup-s3.sh /tmp/aws-backup 202 | ``` 203 | 204 | List the backups available (you will need your passphrase). 205 | 206 | ```bash 207 | borg list /tmp/aws-backup 208 | ``` 209 | 210 | Then create and move to the folder you want to extract your backup in. 211 | 212 | ```bash 213 | mkdir /tmp/extracted-backup && cd /tmp/extracted-backup 214 | ``` 215 | 216 | Finally, extract the backup you need (it will extract in the directory you are located in). 217 | 218 | ```bash 219 | borg extract /tmp/aws-backup::backup-2021-12-06T03.01 220 | ``` 221 | 222 | 223 | # Security 224 | 225 | A few security points : 226 | - Please be careful not to put your bucket publicly visible, by default it should not be. 227 | - You can store your passphrase in [vaultwarden](../vaultwarden). 228 | - Test your backup recovery process, try to download, extract and run your backup to check if everything runs correctly. 229 | - Check the backup scripts and try to understand them, you will have more trust in your backup, that's the beauty of opensource. 230 | 231 | 232 | -------------------------------------------------------------------------------- /borg-backup/backup-borg-s3.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ENV_FILE=$(dirname $0)/.env 4 | if [ ! -f "${ENV_FILE}" ]; then 5 | printf "\n\n** Please create an env file with the required environment variables at '${ENV_FILE}'." 6 | exit 1 7 | fi 8 | # Export env variables 9 | set -o allexport 10 | source .env 11 | set +o allexport 12 | 13 | # Name to give this backup within the borg repo 14 | BACKUP_NAME=backup-$(date +%Y-%m-%dT%H.%M) 15 | 16 | printf "** Starting backup ${BACKUP_NAME} ...\n" 17 | 18 | # Check environment vars are set 19 | if [[ ! "$DOCKER_DIR" ]]; then 20 | printf "\n\n** Please provide with DOCKER_DIR on the environment\n" 21 | exit 1 22 | fi 23 | 24 | if [[ ! "$BORG_REPO" ]]; then 25 | printf "\n\n** Please provide with BORG_REPO on the environment\n" 26 | exit 1 27 | fi 28 | 29 | if [[ ! "$BORG_S3_BACKUP_BUCKET" ]]; then 30 | printf "\n\n** Please provide with BORG_S3_BACKUP_BUCKET on the environment\n" 31 | exit 1 32 | fi 33 | 34 | if [[ ! "$BORG_S3_BACKUP_AWS_PROFILE" ]]; then 35 | printf "\n\n** Please provide with BORG_S3_BACKUP_AWS_PROFILE on the environment (awscli profile)\n" 36 | exit 1 37 | fi 38 | 39 | if [[ ! "$GOTIFY_URL" && ! "$GOTIFY_TOKEN" ]]; then 40 | printf "\n\n** Please provide with GOTIFY_URL and GOTIFY_TOKEN on the environment\n" 41 | exit 1 42 | fi 43 | 44 | SYNC_COMMAND="aws s3 sync ${BORG_REPO} s3://${BORG_S3_BACKUP_BUCKET} --profile=${BORG_S3_BACKUP_AWS_PROFILE} --delete" 45 | 46 | EXCLUDES_FILE=$(dirname $0)/excludes.txt 47 | if [ ! -f "${EXCLUDES_FILE}" ]; then 48 | printf "\n\n** Please create an excludes file (even if empty) at '${EXCLUDES_FILE}'." 49 | exit 1 50 | fi 51 | 52 | # Stopping docker containers to ensure uncorrupted files 53 | printf "\n** Stopping docker containers...\n" 54 | docker stop $(docker ps -a -q) 55 | 56 | # Local borg backup 57 | printf "\n** Backing up ${DOCKER_DIR} with borg...\n" 58 | borg create ::${BACKUP_NAME} ${DOCKER_DIR} --stats --exclude-from ${EXCLUDES_FILE} --compression zlib,6 59 | 60 | # Define and store the backup's exit status 61 | OPERATION_STATUS=$? 62 | 63 | # Only continue if backup was actually successful 64 | if [ $OPERATION_STATUS == 0 ]; then 65 | # Clean up old backups: keep last daily, last weekly and last monthly 66 | printf "\n** Pruning old backups...\n" 67 | borg prune -v --list --keep-daily=1 --keep-weekly=1 --keep-monthly=1 68 | 69 | # Check and compare backup size with threshold 70 | if [[ "$BACKUP_THRESHOLD" && $BACKUP_THRESHOLD != 0 ]]; then 71 | BACKUP_SIZE=$(borg info --json | jq .cache.stats.unique_csize | awk '{ printf "%d", $1/1024/1024/1024; }') 72 | if [[ $BACKUP_SIZE -gt $BACKUP_THRESHOLD ]]; then 73 | printf "Backup size ${BACKUP_SIZE} GB is larger than the threshold ${BACKUP_THRESHOLD} GB" 74 | OPERATION_STATUS=1 75 | MESSAGE="Backup size ${BACKUP_SIZE} GB is larger than the threshold ${BACKUP_THRESHOLD} GB" 76 | fi 77 | fi 78 | fi 79 | 80 | # Sync to AWS if the backup size if lower than the threshold 81 | if [ $OPERATION_STATUS == 0 ]; then 82 | # Sync borg repo to s3 83 | printf "\n** Syncing to s3 bucket ${BORG_S3_BACKUP_BUCKET}...\n" 84 | borg with-lock ${BORG_REPO} ${SYNC_COMMAND} 85 | 86 | # We do care about s3 sync succeeding though 87 | OPERATION_STATUS=$? 88 | fi 89 | 90 | if [ $OPERATION_STATUS == 0 ]; then 91 | # Create Gotify stats 92 | BORG_STATS=$(borg info ::${BACKUP_NAME}) 93 | AWS_STATS=$(aws s3 ls --profile=${BORG_S3_BACKUP_AWS_PROFILE} --summarize --recursive s3://${BORG_S3_BACKUP_BUCKET} | tail -1 | awk '{ printf "%.3f GB", $3/1024/1024/1024; }') 94 | NL=$'\n' 95 | 96 | STATUS_MESSAGE="Backup successful" 97 | MESSAGE="${BORG_STATS}${NL}AWS bucket size : ${AWS_STATS}" 98 | else 99 | STATUS_MESSAGE="Backup failed" 100 | fi 101 | 102 | # Stopping docker containers to ensure uncorrupted files 103 | printf "\n\n** Starting docker containers...\n" 104 | docker start $(docker ps -a -q) 105 | 106 | # Waiting 60s for gotify to start 107 | sleep 60 108 | 109 | # Send gotify notification and exit appropriately 110 | printf "\n** Sending notification to gotify...\n" 111 | if [ $OPERATION_STATUS == 0 ]; then 112 | curl -s "${GOTIFY_URL}/message?token=${GOTIFY_TOKEN}" -F "title=${STATUS_MESSAGE}" -F "message=${MESSAGE}" -F "priority=5" > /dev/null 113 | else 114 | curl -s "${GOTIFY_URL}/message?token=${GOTIFY_TOKEN}" -F "title=${STATUS_MESSAGE}" -F "message=${MESSAGE}" -F "priority=5" > /dev/null 115 | fi 116 | 117 | # Same as above, but on stdout 118 | printf "\n** ${STATUS_MESSAGE}\n" 119 | exit ${OPERATION_STATUS} 120 | -------------------------------------------------------------------------------- /borg-backup/download-backup-s3.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | bold=$(tput bold) 4 | normal=$(tput sgr0) 5 | accent=$(tput setaf 99) 6 | secondary_accent=$(tput setaf 12) 7 | 8 | DOWNLOAD_FOLDER=$1 9 | if [[ ! "$DOWNLOAD_FOLDER" ]]; then 10 | SCRIPT=$(basename "$0") 11 | printf "\n**Please provide the folder we're downloading your backup files into. The folder must exist and be empty.\n" 12 | printf "\nExample: ${SCRIPT} /path/to/folder\n\n" 13 | exit 1 14 | fi 15 | 16 | if [[ ! -d "$DOWNLOAD_FOLDER" ]]; then 17 | printf "\n**The folder ${DOWNLOAD_FOLDER} does not exist. Please create.\n\n" 18 | exit 1 19 | fi 20 | 21 | if [ "$(ls -A $DOWNLOAD_FOLDER)" ]; then 22 | printf "\n**The folder ${DOWNLOAD_FOLDER} is not empty.\n\n" 23 | exit 1 24 | fi 25 | 26 | ENV_FILE=$(dirname $0)/.env 27 | if [ ! -f "${ENV_FILE}" ]; then 28 | printf "\n\n** Please create an env file with the required environment variables at '${ENV_FILE}'." 29 | exit 1 30 | fi 31 | # Export env variables 32 | export $(cat $ENV_FILE | sed 's/#.*//g' | xargs) 33 | 34 | if [[ ! "$BORG_S3_BACKUP_BUCKET" ]]; then 35 | printf "\n\n**Please provide with BORG_S3_BACKUP_BUCKET on the environment\n" 36 | exit 1 37 | fi 38 | 39 | if [[ ! "$BORG_S3_BACKUP_AWS_PROFILE" ]]; then 40 | printf "\n\n**Please provide with BORG_S3_BACKUP_AWS_PROFILE on the environment (awscli profile)\n" 41 | exit 1 42 | fi 43 | 44 | DOWNLOAD_FOLDER_AVAILABLE=$(df -B1 ${DOWNLOAD_FOLDER} | tail -1 | awk '{print $4}') 45 | 46 | printf "${bold}Computing bucket size...${normal}\n\n" 47 | 48 | BUCKET_URI="s3://${BORG_S3_BACKUP_BUCKET}" 49 | BUCKET_SIZE=`aws s3 ls --profile=${BORG_S3_BACKUP_AWS_PROFILE} --summarize --recursive ${BUCKET_URI} | tail -1 | awk '{print \$3}'` 50 | DOWNLOAD_COMMAND="aws s3 sync ${BUCKET_URI} ${DOWNLOAD_FOLDER} --profile=${BORG_S3_BACKUP_AWS_PROFILE}" 51 | 52 | BUCKET_SIZE_GB=`numfmt --to iec --format "%8.4f" ${BUCKET_SIZE}` 53 | DOWNLOAD_FOLDER_AVAILABLE_GB=`numfmt --to iec --format "%8.4f" ${DOWNLOAD_FOLDER_AVAILABLE}` 54 | 55 | echo "${bold}Bucket size:${normal} ${accent}${BUCKET_SIZE_GB}${normal}" 56 | echo "${bold}Available space at ${secondary_accent}${DOWNLOAD_FOLDER}:${normal} ${accent}${DOWNLOAD_FOLDER_AVAILABLE_GB}${normal}" 57 | 58 | if (( $BUCKET_SIZE > $DOWNLOAD_FOLDER_AVAILABLE )); then 59 | printf "\n**There is not enough space to download your backup at ${secondary_accent}${DOWNLOAD_FOLDER}${normal}\n" 60 | exit 1 61 | fi 62 | 63 | printf "\n${bold}Starting download: ${secondary_accent}${BUCKET_URI} ${accent}--> ${secondary_accent}${DOWNLOAD_FOLDER}${normal}\n\n" 64 | 65 | $DOWNLOAD_COMMAND 66 | 67 | printf "\n\n${bold}Backup download success.\n\n" -------------------------------------------------------------------------------- /borg-backup/excludes.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaptisteBdn/docker-selfhosted-apps/70e8ee22b1a1d2f0c2bf4940301b565928ac2b95/borg-backup/excludes.txt -------------------------------------------------------------------------------- /fail2ban/.env: -------------------------------------------------------------------------------- 1 | TZ=Europe/Paris -------------------------------------------------------------------------------- /fail2ban/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | Fail2ban 5 |

6 | 7 | Fail2ban scans log files and bans IPs that show the malicious signs. 8 | 9 | * [Github](https://github.com/fail2ban/fail2ban) 10 | * [Documentation](http://www.fail2ban.org/wiki/index.php/Fail2Ban) 11 | * [Docker Image](https://github.com/crazy-max/docker-fail2ban) 12 | 13 | We are going to be using a prebuilt docker image by crazymax to facilitate the process. 14 | There are a lot of fail2ban configurations availabe on the internet, and you can even create your own, this guide provides the following features : 15 | 16 | - SSH jail configuration 17 | - Vaultwarden jail configuration 18 | 19 | # Table of Contents 20 | 21 | 22 | 23 | - [About](#about) 24 | - [Table of Contents](#table-of-contents) 25 | - [Files structure](#files-structure) 26 | - [Information](#information) 27 | - [docker-compose](#docker-compose) 28 | - [jails](#jails) 29 | - [Usage](#usage) 30 | - [Configuration](#configuration) 31 | - [Fail2ban](#fail2ban) 32 | - [Update](#update) 33 | - [Security](#security) 34 | - [Backup](#backup) 35 | 36 | 37 | 38 | # Files structure 39 | ```bash 40 | . 41 | |-- data/ 42 | | |-- action.d/ 43 | | | |-- nftables-forward.conf 44 | | | |-- nftables-input.conf 45 | | |-- db/ 46 | | |-- filter.d/ 47 | | | |-- bitwarden-admin.conf 48 | | | |-- bitwarden-auth.conf 49 | | `-- jail.d/ 50 | | |-- bitwarden-admin.conf 51 | | |-- bitwarden-auth.conf 52 | | |-- sshd.conf 53 | `-- docker-compose.yml 54 | ``` 55 | 56 | - `data/action.d` - a directory containing custom action configuration to execute when banning an IP 57 | - `data/db` - a directory used to store fail2ban sqlite database 58 | - `data/filter.d` - a directory containing custom filter configuration used by a jail to match malicious signs 59 | - `data/jail.d` - a directory containing custom jail configuration for your services 60 | - `docker-compose.yml` - a docker-compose file, use to configure your application’s services 61 | 62 | Please make sure that all the files and directories are present. 63 | 64 | 65 | # Information 66 | 67 | ## docker-compose 68 | Links to the following [docker-compose.yml](docker-compose.yml) and the corresponding [.env](.env). 69 | 70 | * docker-compose.yml 71 | ```yaml 72 | version: '3' 73 | 74 | services: 75 | fail2ban: 76 | image: crazymax/fail2ban:latest 77 | container_name: fail2ban 78 | restart: unless-stopped 79 | volumes: 80 | - /var/log:/var/log:ro 81 | - ./data:/data 82 | environment: 83 | - TZ=${TZ} 84 | network_mode: host 85 | cap_add: 86 | - NET_ADMIN 87 | - NET_RAW 88 | labels: 89 | # Watchtower Update 90 | - "com.centurylinklabs.watchtower.enable=true" 91 | ``` 92 | * .env 93 | ```ini 94 | TZ=Europe/Paris 95 | ``` 96 | 97 | We are gonna use `/var/log` directory to parse log files. 98 | 99 | ## jails 100 | 101 | The jail.d directory is provided with three examples. 102 | 103 | - sshd.conf : provides ssh protection, will ban any IP trying to bruteforce your ssh credentials, a must-have if you are still on port 22. 104 | 105 | - bitwarden-auth.conf : provides your vaultwarden password manager from bruteforce. 106 | 107 | - bitwarden-admin.conf : provides your vaultwarden admin dashboard from bruteforce. 108 | 109 | You can find the vaultwarden filters in the filter.d directory. For example, in `filter.d/vaultwarden-auth` you can find : 110 | 111 | ```ini 112 | [INCLUDES] 113 | before = common.conf 114 | 115 | [Definition] 116 | failregex = ^.*Username or password is incorrect\. Try again\. IP: \. Username:.*$ 117 | ignoreregex = 118 | ``` 119 | 120 | This filter is using regex and will match any log that fails to connect to your vaultwarden vault. The log file that is parsed is `/var/log/syslog`, redirection is provided with the docker-compose available in the [vaultwarden guide](../vaultwarden). 121 | 122 | # Usage 123 | 124 | ## Configuration 125 | 126 | Replace the environment variables in `.env` with your own, then run : 127 | 128 | ```bash 129 | sudo docker-compose up -d 130 | ``` 131 | 132 | The jails and filters configured are going to be active, you can now create as many as you want to protect your services. 133 | 134 | ## Fail2ban 135 | 136 | [Fail2ban commands](http://www.fail2ban.org/wiki/index.php/Commands) can be used through the container. 137 | Here is an example if you want to unban an IP manually: 138 | 139 | ``` 140 | sudo docker exec -t fail2ban fail2ban-client set unbanip 141 | ``` 142 | 143 | The same example with [bitwarden](../vaultwarden), in the case you failed to enter the right password 3 times: 144 | ``` 145 | sudo docker exec -t fail2ban fail2ban-client set bitwarden-auth unbanip 146 | ``` 147 | 148 | For a more general example, you can use any fail2ban command as follows: 149 | ``` 150 | sudo docker exec -t fail2ban fail2ban-client 151 | ``` 152 | 153 | # Update 154 | 155 | The image is automatically updated with [watchtower](../watchtower) thanks to the following label : 156 | 157 | ```yaml 158 | # Watchtower Update 159 | - "com.centurylinklabs.watchtower.enable=true" 160 | ``` 161 | 162 | # Security 163 | 164 | Be careful not to get ban as the iptable action is pretty aggressive, you will not be able to SSH with the banned IP. 165 | 166 | # Backup 167 | 168 | Docker volumes are globally backed up using [borg-backup](../borg-backup). -------------------------------------------------------------------------------- /fail2ban/data/action.d/nftables-forward.conf: -------------------------------------------------------------------------------- 1 | [INCLUDES] 2 | before = nftables.conf 3 | 4 | [Init] 5 | chain = f2b-chain-forward 6 | chain_hook = forward -------------------------------------------------------------------------------- /fail2ban/data/action.d/nftables-input.conf: -------------------------------------------------------------------------------- 1 | [INCLUDES] 2 | before = nftables.conf 3 | 4 | [Init] 5 | chain = f2b-chain-input 6 | chain_hook = input -------------------------------------------------------------------------------- /fail2ban/data/filter.d/bitwarden-admin.conf: -------------------------------------------------------------------------------- 1 | [INCLUDES] 2 | before = common.conf 3 | 4 | [Definition] 5 | failregex = ^.*Invalid admin token\. IP: .*$ 6 | ignoreregex = 7 | -------------------------------------------------------------------------------- /fail2ban/data/filter.d/bitwarden-auth.conf: -------------------------------------------------------------------------------- 1 | [INCLUDES] 2 | before = common.conf 3 | 4 | [Definition] 5 | failregex = ^.*Username or password is incorrect\. Try again\. IP: \. Username:.*$ 6 | ignoreregex = 7 | -------------------------------------------------------------------------------- /fail2ban/data/jail.d/bitwarden-admin.conf: -------------------------------------------------------------------------------- 1 | [bitwarden-admin] 2 | enabled = true 3 | banaction = nftables-forward 4 | logpath = /var/log/syslog 5 | maxretry = 5 6 | bantime = 14400 7 | findtime = 14400 -------------------------------------------------------------------------------- /fail2ban/data/jail.d/bitwarden-auth.conf: -------------------------------------------------------------------------------- 1 | [bitwarden-auth] 2 | enabled = true 3 | banaction = nftables-forward 4 | logpath = /var/log/syslog 5 | maxretry = 3 6 | bantime = 14400 7 | findtime = 14400 -------------------------------------------------------------------------------- /fail2ban/data/jail.d/sshd.conf: -------------------------------------------------------------------------------- 1 | [sshd] 2 | enabled = true 3 | chain = INPUT 4 | port = ssh 5 | filter = sshd[mode=aggressive] 6 | logpath = /var/log/auth.log 7 | maxretry = 3 8 | bantime = 14400 9 | findtime = 14400 10 | -------------------------------------------------------------------------------- /fail2ban/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | fail2ban: 5 | image: crazymax/fail2ban:latest 6 | container_name: fail2ban 7 | restart: unless-stopped 8 | volumes: 9 | - /var/log:/var/log:ro 10 | - ./data:/data 11 | environment: 12 | - TZ=${TZ} 13 | network_mode: host 14 | cap_add: 15 | - NET_ADMIN 16 | - NET_RAW 17 | labels: 18 | # Watchtower Update 19 | - "com.centurylinklabs.watchtower.enable=true" 20 | -------------------------------------------------------------------------------- /freshrss/.env: -------------------------------------------------------------------------------- 1 | TRAEFIK_FRESHRSS=freshrss.example.com 2 | TZ=Europe/Paris -------------------------------------------------------------------------------- /freshrss/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | freshrss 5 |

6 | 7 | FreshRSS is a self-hosted RSS feed aggregator 8 | 9 | * [Github](https://github.com/FreshRSS/FreshRSS) 10 | * [Documentation](https://freshrss.github.io/FreshRSS/en/admins/01_Index.html) 11 | * [Docker Image](https://hub.docker.com/r/linuxserver/freshrss) 12 | 13 | # Table of Contents 14 | 15 | 16 | 17 | - [About](#about) 18 | - [Table of Contents](#table-of-contents) 19 | - [Information](#information) 20 | - [docker-compose](#docker-compose) 21 | - [Usage](#usage) 22 | - [Requirements](#requirements) 23 | - [Configuration](#configuration) 24 | - [Update](#update) 25 | - [Backup](#backup) 26 | 27 | 28 | 29 | ```bash 30 | . 31 | |-- .env 32 | |-- data/ 33 | `-- docker-compose.yml 34 | ``` 35 | 36 | * `.env` - a file containing all the environment variables used in the docker-compose.yml 37 | * `docker-compose.yml` - a docker-compose file, use to configure your application’s services 38 | * `data/` - a directory used to store the data 39 | 40 | Please make sure that all the files and directories are present. 41 | 42 | # Information 43 | 44 | ## docker-compose 45 | 46 | Links to the following [docker-compose.yml](docker-compose.yml) and the corresponding [.env](.env). 47 | 48 | * docker-compose.yml 49 | ```yaml 50 | version: '3' 51 | 52 | services: 53 | freshrss: 54 | image: 'freshrss/freshrss' 55 | container_name: freshrss 56 | restart: unless-stopped 57 | volumes: 58 | - "./data:/var/www/FreshRSS/data" 59 | environment: 60 | - 'CRON_MIN=4,34' 61 | - 'TZ=Europe/Paris' 62 | networks: 63 | - proxy 64 | labels: 65 | - "traefik.enable=true" 66 | - "traefik.http.routers.webserver.rule=Host(`${TRAEFIK_FRESHRSS}`)" 67 | - "traefik.http.routers.webserver.entrypoints=https" 68 | - "traefik.http.routers.webserver.tls=true" 69 | - "traefik.http.routers.webserver.tls.certresolver=mydnschallenge" 70 | # Watchtower Update 71 | - "com.centurylinklabs.watchtower.enable=true" 72 | 73 | networks: 74 | proxy: 75 | external: true 76 | ``` 77 | * .env 78 | ```ini 79 | TRAEFIK_FRESHRSS=freshrss.example.com 80 | TZ=Europe/Paris 81 | ``` 82 | 83 | The docker-compose contains only one service using the freshrss image. 84 | 85 | # Usage 86 | 87 | ## Requirements 88 | 89 | * [Traefik up and running](../traefik). 90 | * A subdomain of your choice, this example uses `freshrss`. 91 | * You should be able to create a subdomain with your DNS provider, use a `A record` with the same IP address as your root domain. 92 | 93 | ## Configuration 94 | 95 | Replace the environment variables in `.env` with your own, then run : 96 | 97 | ```bash 98 | sudo docker-compose up -d 99 | ``` 100 | 101 | You should now be able to access the freshrss setup instruction, it is quite straigthforward and nothing is required. 102 | 103 | # Update 104 | 105 | The image is automatically updated with [watchtower](../watchtower) thanks to the following label : 106 | 107 | ```yaml 108 | # Watchtower Update 109 | - "com.centurylinklabs.watchtower.enable=true" 110 | ``` 111 | 112 | # Backup 113 | 114 | Docker volumes are globally backed up using [borg-backup](../borg-backup). 115 | -------------------------------------------------------------------------------- /freshrss/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | freshrss: 5 | image: 'freshrss/freshrss' 6 | container_name: freshrss 7 | restart: unless-stopped 8 | volumes: 9 | - "./data:/var/www/FreshRSS/data" 10 | environment: 11 | - 'CRON_MIN=4,34' 12 | - 'TZ=Europe/Paris' 13 | networks: 14 | - proxy 15 | labels: 16 | - "traefik.enable=true" 17 | - "traefik.http.routers.freshrss.rule=Host(`${TRAEFIK_FRESHRSS}`)" 18 | - "traefik.http.routers.freshrss.entrypoints=https" 19 | - "traefik.http.routers.freshrss.tls=true" 20 | - "traefik.http.routers.freshrss.tls.certresolver=mydnschallenge" 21 | # Watchtower Update 22 | - "com.centurylinklabs.watchtower.enable=true" 23 | 24 | networks: 25 | proxy: 26 | external: true -------------------------------------------------------------------------------- /gotify/.env: -------------------------------------------------------------------------------- 1 | TRAEFIK_GOTIFY=gotify.example.com 2 | GOTIFY_DEFAULTUSER_PASS=xxxxxxxxxxxxxxxxx 3 | -------------------------------------------------------------------------------- /gotify/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | gotify 5 |

6 | 7 | Gotify is a simple server for sending and receiving notification messages. It is used a lot throughout this guide for services such as backups and automatic updates, a must-have self-hosted solution. 8 | 9 | * [Github](https://github.com/gotify/server) 10 | * [Documentation](https://gotify.net/docs/index) 11 | * [Docker Image](https://hub.docker.com/r/gotify/server) 12 | 13 | # Table of Contents 14 | 15 | 16 | 17 | - [About](#about) 18 | - [Table of Contents](#table-of-contents) 19 | - [Files structure](#files-structure) 20 | - [Information](#information) 21 | - [docker-compose](#docker-compose) 22 | - [Usage](#usage) 23 | - [Requirements](#requirements) 24 | - [Configuration](#configuration) 25 | - [Update](#update) 26 | - [Security](#security) 27 | - [Backup](#backup) 28 | 29 | 30 | 31 | # Files structure 32 | 33 | ```bash 34 | . 35 | |-- .env 36 | |-- docker-compose.yml 37 | `-- data/ 38 | ``` 39 | 40 | - `.env` - a file containing all the environment variables used in the docker-compose.yml 41 | - `docker-compose.yml` - a docker-compose file, use to configure your application’s services 42 | - `data/` - a directory used to store the service's data 43 | 44 | Please make sure that all the files and directories are present. 45 | 46 | 47 | # Information 48 | 49 | ## docker-compose 50 | Links to the following [docker-compose.yml](docker-compose.yml) and the corresponding [.env](.env). 51 | 52 | * docker-compose.yml 53 | ```yaml 54 | version: "3" 55 | 56 | services: 57 | gotify: 58 | image: gotify/server 59 | container_name: gotify 60 | restart: unless-stopped 61 | volumes: 62 | - "./data:/app/data" 63 | environment: 64 | - GOTIFY_DEFAULTUSER_PASS=${GOTIFY_DEFAULTUSER_PASS} 65 | networks: 66 | - proxy 67 | labels: 68 | - "traefik.enable=true" 69 | - "traefik.http.routers.gotify.rule=Host(`gotify.example.com`)" 70 | - "traefik.http.routers.gotify.entrypoints=https" 71 | - "traefik.http.routers.gotify.tls=true" 72 | - "traefik.http.routers.gotify.tls.certresolver=mydnschallenge" 73 | 74 | # Watchtower Update 75 | - "com.centurylinklabs.watchtower.enable=true" 76 | 77 | networks: 78 | proxy: 79 | external: true 80 | ``` 81 | * .env 82 | ```ini 83 | TRAEFIK_GOTIFY=gotify.example.com 84 | GOTIFY_DEFAULTUSER_PASS=xxxxxxxxxxxxxxxxx 85 | ``` 86 | 87 | # Usage 88 | 89 | ## Requirements 90 | - [Traefik up and running](../traefik). 91 | - A subdomain of your choice, this example uses `gotify`. 92 | - You should be able to create a subdomain with your DNS provider, use a `A record` with the same IP address as your root domain. 93 | 94 | ## Configuration 95 | 96 | Replace the environment variables in `.env` with your own, then run : 97 | 98 | ```bash 99 | sudo docker-compose up -d 100 | ``` 101 | 102 | You should then be able to access the gotify web-ui with the default user being `admin` and the GOTIFY_DEFAULTUSER_PASS defined in `.env`. 103 | 104 | # Update 105 | 106 | The image is automatically updated with [watchtower](../watchtower) thanks to the following label : 107 | 108 | ```yaml 109 | # Watchtower Update 110 | - "com.centurylinklabs.watchtower.enable=true" 111 | ``` 112 | 113 | # Security 114 | 115 | Don't forget to change the GOTIFY_DEFAULTUSER_PASS after first using it. 116 | 117 | # Backup 118 | 119 | Docker volumes are globally backed up using [borg-backup](../borg-backup). -------------------------------------------------------------------------------- /gotify/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | gotify: 5 | image: gotify/server 6 | container_name: gotify 7 | restart: unless-stopped 8 | volumes: 9 | - "./data:/app/data" 10 | environment: 11 | - GOTIFY_DEFAULTUSER_PASS=${GOTIFY_DEFAULTUSER_PASS} 12 | networks: 13 | - proxy 14 | labels: 15 | - "traefik.enable=true" 16 | - "traefik.http.routers.gotify.rule=Host(`${TRAEFIK_GOTIFY}`)" 17 | - "traefik.http.routers.gotify.entrypoints=https" 18 | - "traefik.http.routers.gotify.tls=true" 19 | - "traefik.http.routers.gotify.tls.certresolver=mydnschallenge" 20 | 21 | # Watchtower Update 22 | - "com.centurylinklabs.watchtower.enable=true" 23 | 24 | networks: 25 | proxy: 26 | external: true -------------------------------------------------------------------------------- /jellyfin/.env: -------------------------------------------------------------------------------- 1 | TRAEFIK_JELLYFIN=jellyfin.example.com -------------------------------------------------------------------------------- /jellyfin/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | jellyfin 5 |

6 | 7 | Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media. 8 | 9 | * [Github](https://github.com/jellyfin/jellyfin) 10 | * [Documentation](https://jellyfin.org/docs/) 11 | * [Docker Image](https://hub.docker.com/r/jellyfin/jellyfin/) 12 | 13 | # Table of Contents 14 | 15 | 16 | 17 | - [About](#about) 18 | - [Table of Contents](#table-of-contents) 19 | - [Files structure](#files-structure) 20 | - [Information](#information) 21 | - [docker-compose](#docker-compose) 22 | - [Usage](#usage) 23 | - [Requirements](#requirements) 24 | - [Configuration](#configuration) 25 | - [Note](#note) 26 | - [Update](#update) 27 | - [Backup](#backup) 28 | 29 | 30 | 31 | # Files structure 32 | 33 | ```bash 34 | . 35 | |-- .env 36 | |-- cache/ 37 | |-- config/ 38 | |-- docker-compose.yml 39 | `-- media/ 40 | ``` 41 | 42 | - `.env` - a file containing all the environment variables used in the docker-compose.yml 43 | - `docker-compose.yml` - a docker-compose file, use to configure your application’s services 44 | - `cache/` - a directory used to store jellyfin caching data (optionnal) 45 | - `config/` - a directory used to store jellyfin config data 46 | - `media/` - a directory used to store media that will be scanned by jellyfin 47 | 48 | Please make sure that all the files and directories are present. 49 | 50 | # Information 51 | 52 | ## docker-compose 53 | Links to the following [docker-compose.yml](docker-compose.yml) and the corresponding [.env](.env). 54 | 55 | * docker-compose.yml 56 | ```yaml 57 | version: '3' 58 | 59 | services: 60 | jellyfin: 61 | image: jellyfin/jellyfin 62 | container_name: jellyfin 63 | volumes: 64 | - ./config:/config 65 | - ./cache:/cache 66 | - ./media:/media 67 | labels: 68 | - "traefik.enable=true" 69 | - "traefik.http.routers.jellyfin.rule=Host(`${TRAEFIK_JELLYFIN}`)" 70 | - "traefik.http.routers.jellyfin.entrypoints=https" 71 | - "traefik.http.routers.jellyfin.tls=true" 72 | - "traefik.http.routers.jellyfin.tls.certresolver=mydnschallenge" 73 | 74 | # Watchtower Update 75 | - "com.centurylinklabs.watchtower.enable=true" 76 | networks: 77 | - proxy 78 | 79 | networks: 80 | proxy: 81 | external: true 82 | ``` 83 | * .env 84 | ```ini 85 | TRAEFIK_JELLYFIN=jellyfin.example.com 86 | ``` 87 | 88 | # Usage 89 | 90 | ## Requirements 91 | - [Traefik up and running](../traefik). 92 | - A subdomain of your choice, this example uses `jellyfin`. 93 | - You should be able to create a subdomain with your DNS provider, use a `A record` with the same IP address as your root domain. 94 | 95 | ## Configuration 96 | 97 | Replace the environment variables in `.env` with your own, then run : 98 | 99 | ```bash 100 | sudo docker-compose up -d 101 | ``` 102 | 103 | You should then be able to access the jellyfin web-ui. 104 | 105 | ## Note 106 | 107 | Jellyfin can be combined with [transmission](../transmission), download any media you want and watch them directly on jellyfin ! 108 | In order to do that, you can configure a volume on transmission that will link to the volume in Jellyfin or the opposite. 109 | 110 | In transmission, you could replace 111 | ``` 112 | - ./data/downloads:/downloads 113 | ``` 114 | With : 115 | ``` 116 | - ../jellyfin/media:/downloads 117 | ``` 118 | 119 | This can be configured more precisely, depending on your use-case. 120 | 121 | # Update 122 | 123 | The image is automatically updated with [watchtower](../watchtower) thanks to the following label : 124 | 125 | ```yaml 126 | # Watchtower Update 127 | - "com.centurylinklabs.watchtower.enable=true" 128 | ``` 129 | 130 | # Backup 131 | 132 | Docker volumes are globally backed up using [borg-backup](../borg-backup). 133 | 134 | You may want to exclude the cache and media folder from the backups, add the following to [`borg-backup/excludes.txt`](../borg-backup/excludes.txt): 135 | ``` 136 | /full/path/to/jellyfin/cache 137 | /full/path/to/jellyfin/media 138 | ``` 139 | -------------------------------------------------------------------------------- /jellyfin/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | jellyfin: 5 | image: jellyfin/jellyfin 6 | container_name: jellyfin 7 | volumes: 8 | - ./config:/config 9 | - ./cache:/cache 10 | - ./media:/media 11 | labels: 12 | - "traefik.enable=true" 13 | - "traefik.http.routers.jellyfin.rule=Host(`${TRAEFIK_JELLYFIN}`)" 14 | - "traefik.http.routers.jellyfin.entrypoints=https" 15 | - "traefik.http.routers.jellyfin.tls=true" 16 | - "traefik.http.routers.jellyfin.tls.certresolver=mydnschallenge" 17 | 18 | # Watchtower Update 19 | - "com.centurylinklabs.watchtower.enable=true" 20 | networks: 21 | - proxy 22 | 23 | networks: 24 | proxy: 25 | external: true -------------------------------------------------------------------------------- /nextcloud/.env: -------------------------------------------------------------------------------- 1 | TRAEFIK_NEXTCLOUD=nextcloud.example.com 2 | DB_ROOT_PASSWD=xxxxxxxxxxxxxxx 3 | DB_PASSWD=xxxxxxxxxxxxxxx -------------------------------------------------------------------------------- /nextcloud/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | nextcloud 5 |

6 | 7 | Nextcloud is a safe home for all your data. Access & share your files, calendars, contacts, mail & more from any device, on your terms. 8 | 9 | * [Github](https://github.com/nextcloud/docker) 10 | * [Documentation](https://docs.nextcloud.com/server/latest/admin_manual/contents.html) 11 | * [Docker Image](https://hub.docker.com/_/nextcloud) 12 | 13 | # Table of Contents 14 | 15 | 16 | 17 | - [About](#about) 18 | - [Table of Contents](#table-of-contents) 19 | - [Files structure](#files-structure) 20 | - [Information](#information) 21 | - [docker-compose](#docker-compose) 22 | - [Usage](#usage) 23 | - [Requirements](#requirements) 24 | - [Configuration](#configuration) 25 | - [Update](#update) 26 | - [Security](#security) 27 | - [Backup](#backup) 28 | 29 | 30 | 31 | # Files structure 32 | 33 | ```bash 34 | . 35 | |-- .env 36 | |-- docker-compose.yml 37 | |-- nextcloud-mysql/ 38 | `-- shared/ 39 | ``` 40 | 41 | - `.env` - a file containing all the environment variables used in the docker-compose.yml 42 | - `docker-compose.yml` - a docker-compose file, use to configure your application’s services 43 | - `nextcloud-mysql/` - a directory used to store the mysql data 44 | - `shared/` - a directory used to store nextcloud's data 45 | 46 | Please make sure that all the files and directories are present. 47 | 48 | # Information 49 | 50 | ## docker-compose 51 | Links to the following [docker-compose.yml](docker-compose.yml) and the corresponding [.env](.env). 52 | 53 | * docker-compose.yml 54 | ```yaml 55 | version: '3' 56 | 57 | services: 58 | db: 59 | image: mariadb:10.5 60 | container_name: nextcloud-mysql 61 | restart: unless-stopped 62 | command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW 63 | volumes: 64 | - ./nextcloud-mysql/db:/var/lib/mysql 65 | environment: 66 | - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWD} # Requested, set the root's password of MySQL service. 67 | - MYSQL_PASSWORD=${DB_PASSWD} 68 | - MYSQL_DATABASE=nextcloud 69 | - MYSQL_USER=nextcloud 70 | - MYSQL_LOG_CONSOLE=true 71 | networks: 72 | - nextcloud-net 73 | labels: 74 | # Watchtower Update 75 | - "com.centurylinklabs.watchtower.enable=true" 76 | 77 | nextcloud: 78 | image: nextcloud:latest 79 | container_name: nextcloud 80 | restart: unless-stopped 81 | volumes: 82 | - ./shared:/shared 83 | networks: 84 | - proxy 85 | - nextcloud-net 86 | depends_on: 87 | - db 88 | labels: 89 | - "traefik.enable=true" 90 | - "traefik.http.routers.nextcloud.rule=Host(`${TRAEFIK_NEXTCLOUD}`)" 91 | - "traefik.http.routers.nextcloud.entrypoints=https" 92 | - "traefik.http.routers.nextcloud.tls=true" 93 | - "traefik.http.routers.nextcloud.tls.certresolver=mydnschallenge" 94 | # Watchtower Update 95 | - "com.centurylinklabs.watchtower.enable=true" 96 | # Ip filtering 97 | - "traefik.http.routers.nextcloud.middlewares=whitelist@file" 98 | 99 | networks: 100 | nextcloud-net: 101 | proxy: 102 | external: true 103 | ``` 104 | * .env 105 | ```ini 106 | TRAEFIK_NEXTCLOUD=nextcloud.example.com 107 | DB_ROOT_PASSWD=xxxxxxxxxxxxxxx 108 | DB_PASSWD=xxxxxxxxxxxxxxx 109 | ``` 110 | 111 | 112 | 113 | # Usage 114 | 115 | ## Requirements 116 | - [Traefik up and running](../traefik). 117 | - A subdomain of your choice, this example uses `nextcloud`. 118 | - You should be able to create a subdomain with your DNS provider, use a `A record` with the same IP address as your root domain. 119 | 120 | ## Configuration 121 | 122 | Replace the environment variables in `.env` with your own, then run : 123 | 124 | ```bash 125 | sudo docker-compose up -d 126 | ``` 127 | 128 | You should now be able to access the nextcloud admin account creation. 129 | Nextcloud will ask you to create your admin account as well as to choose what type of database your want to use. In the docker-compose we set up a mariadb database, choose it and enter the following database credentials. 130 | 131 |

132 | nextcloud_instruction 133 |

134 | 135 | The password is the one you have modified in the `.env` file : DB_PASSWD. 136 | Nextcloud will now finish installing and will soon be ready to use. 137 | 138 | 139 | # Update 140 | 141 | The image is automatically updated with [watchtower](../watchtower) thanks to the following label : 142 | 143 | ```yaml 144 | # Watchtower Update 145 | - "com.centurylinklabs.watchtower.enable=true" 146 | ``` 147 | 148 | # Security 149 | 150 | Nextcloud provides client-side end-to-end data encryption. You can create encrypted libraries to use this feature. Use this feature to add extra security to your documents. 151 | 152 | # Backup 153 | 154 | Docker volumes are globally backed up using [borg-backup](../borg-backup). -------------------------------------------------------------------------------- /nextcloud/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | db: 5 | image: mariadb:10.5 6 | container_name: nextcloud-mysql 7 | restart: unless-stopped 8 | command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW 9 | volumes: 10 | - ./nextcloud-mysql/db:/var/lib/mysql 11 | environment: 12 | - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWD} # Requested, set the root's password of MySQL service. 13 | - MYSQL_PASSWORD=${DB_PASSWD} 14 | - MYSQL_DATABASE=nextcloud 15 | - MYSQL_USER=nextcloud 16 | - MYSQL_LOG_CONSOLE=true 17 | networks: 18 | - nextcloud-net 19 | labels: 20 | # Watchtower Update 21 | - "com.centurylinklabs.watchtower.enable=true" 22 | 23 | nextcloud: 24 | image: nextcloud:latest 25 | container_name: nextcloud 26 | restart: unless-stopped 27 | volumes: 28 | - ./shared:/shared 29 | networks: 30 | - proxy 31 | - nextcloud-net 32 | depends_on: 33 | - db 34 | labels: 35 | - "traefik.enable=true" 36 | - "traefik.http.routers.nextcloud.rule=Host(`${TRAEFIK_NEXTCLOUD}`)" 37 | - "traefik.http.routers.nextcloud.entrypoints=https" 38 | - "traefik.http.routers.nextcloud.tls=true" 39 | - "traefik.http.routers.nextcloud.tls.certresolver=mydnschallenge" 40 | # Watchtower Update 41 | - "com.centurylinklabs.watchtower.enable=true" 42 | # Ip filtering 43 | - "traefik.http.routers.nextcloud.middlewares=whitelist@file" 44 | 45 | networks: 46 | nextcloud-net: 47 | proxy: 48 | external: true -------------------------------------------------------------------------------- /seafile/.env: -------------------------------------------------------------------------------- 1 | TRAEFIK_SEAFILE=seafile.example.com 2 | DB_ROOT_PASSWD=xxxxxxxxxxxxxxx 3 | SEAFILE_ADMIN_EMAIL=admin@example.com 4 | SEAFILE_ADMIN_PASSWORD=xxxxxxxxxxxxxxxx -------------------------------------------------------------------------------- /seafile/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | seafile 5 |

6 | 7 | Seafile is an open-source, cross-platform file-hosting software system. Files are stored on a central server and can be synchronized with personal computers and mobile devices through apps or through the web interface. 8 | 9 | * [Github](https://github.com/haiwen/seafile) 10 | * [Documentation](https://manual.seafile.com/docker/deploy_seafile_with_docker/) 11 | * [Docker Image](https://hub.docker.com/r/seafileltd/seafile-mc) 12 | 13 | # Table of Contents 14 | 15 | 16 | 17 | - [About](#about) 18 | - [Table of Contents](#table-of-contents) 19 | - [Files structure](#files-structure) 20 | - [Information](#information) 21 | - [docker-compose](#docker-compose) 22 | - [Usage](#usage) 23 | - [Requirements](#requirements) 24 | - [Configuration](#configuration) 25 | - [Update](#update) 26 | - [Security](#security) 27 | - [Backup](#backup) 28 | 29 | 30 | 31 | # Files structure 32 | 33 | ```bash 34 | . 35 | |-- .env 36 | |-- docker-compose.yml 37 | |-- seafile-mysql/ 38 | `-- shared/ 39 | ``` 40 | 41 | - `.env` - a file containing all the environment variables used in the docker-compose.yml 42 | - `docker-compose.yml` - a docker-compose file, use to configure your application’s services 43 | - `seafile-mysql/` - a directory used to store the mysql data 44 | - `shared/` - a directory used to store seafile's data 45 | 46 | Please make sure that all the files and directories are present. 47 | 48 | # Information 49 | 50 | ## docker-compose 51 | Links to the following [docker-compose.yml](docker-compose.yml) and the corresponding [.env](.env). 52 | 53 | * docker-compose.yml 54 | ```yaml 55 | version: '3' 56 | 57 | services: 58 | db: 59 | image: mariadb:10.5 60 | container_name: seafile-mysql 61 | restart: unless-stopped 62 | volumes: 63 | - ./seafile-mysql/db:/var/lib/mysql 64 | environment: 65 | - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWD} # Requested, set the root's password of MySQL service. 66 | - MYSQL_LOG_CONSOLE=true 67 | networks: 68 | - seafile-net 69 | labels: 70 | # Watchtower Update 71 | - "com.centurylinklabs.watchtower.enable=true" 72 | 73 | memcached: 74 | image: memcached:latest 75 | container_name: seafile-memcached 76 | restart: unless-stopped 77 | entrypoint: memcached -m 256 78 | networks: 79 | - seafile-net 80 | labels: 81 | # Watchtower Update 82 | - "com.centurylinklabs.watchtower.enable=true" 83 | 84 | seafile: 85 | image: seafileltd/seafile-mc:latest 86 | container_name: seafile 87 | restart: unless-stopped 88 | volumes: 89 | - ./shared:/shared 90 | environment: 91 | - DB_HOST=db 92 | - DB_ROOT_PASSWD=${DB_ROOT_PASSWD} # Requested, the value shuold be root's password of MySQL service. 93 | - SEAFILE_ADMIN_EMAIL=${SEAFILE_ADMIN_EMAIL} # Specifies Seafile admin user, default is 'me@example.com'. 94 | - SEAFILE_ADMIN_PASSWORD=${SEAFILE_ADMIN_PASSWORD} # Specifies Seafile admin password, default is 'asecret'. 95 | - SEAFILE_SERVER_LETSENCRYPT=false # Whether to use https or not. 96 | - SEAFILE_SERVER_HOSTNAME=${TRAEFIK_SEAFILE} # Specifies your host name if https is enabled. 97 | - SEAFILE_SERVICE_URL=https://${TRAEFIK_SEAFILE} 98 | networks: 99 | - proxy 100 | - seafile-net 101 | depends_on: 102 | - db 103 | - memcached 104 | labels: 105 | - "traefik.enable=true" 106 | - "traefik.http.routers.seafile.rule=Host(`${TRAEFIK_SEAFILE}`)" 107 | - "traefik.http.routers.seafile.entrypoints=https" 108 | - "traefik.http.routers.seafile.tls=true" 109 | - "traefik.http.routers.seafile.tls.certresolver=mydnschallenge" 110 | # Watchtower Update 111 | - "com.centurylinklabs.watchtower.enable=true" 112 | # Ip filtering 113 | - "traefik.http.routers.seafile.middlewares=whitelist@file" 114 | 115 | networks: 116 | seafile-net: 117 | proxy: 118 | external: true 119 | ``` 120 | * .env 121 | ```ini 122 | TRAEFIK_SEAFILE=seafile.example.com 123 | DB_ROOT_PASSWD=xxxxxxxxxxxxxxx 124 | SEAFILE_ADMIN_EMAIL=admin@example.com 125 | SEAFILE_ADMIN_PASSWORD=xxxxxxxxxxxxxxxx 126 | ``` 127 | 128 | # Usage 129 | 130 | ## Requirements 131 | - [Traefik up and running](../traefik). 132 | - A subdomain of your choice, this example uses `seafile`. 133 | - You should be able to create a subdomain with your DNS provider, use a `A record` with the same IP address as your root domain. 134 | 135 | ## Configuration 136 | 137 | Replace the environment variables in `.env` with your own, then run : 138 | 139 | ```bash 140 | sudo docker-compose up -d 141 | ``` 142 | 143 | You should then be able to access the seafile web-ui with the SEAFILE_ADMIN_EMAIL and SEAFILE_ADMIN_PASSWORD. 144 | 145 | # Update 146 | 147 | The image is automatically updated with [watchtower](../watchtower) thanks to the following label : 148 | 149 | ```yaml 150 | # Watchtower Update 151 | - "com.centurylinklabs.watchtower.enable=true" 152 | ``` 153 | 154 | # Security 155 | 156 | Seafile provides client-side end-to-end data encryption. You can create encrypted libraries to use this feature. Use this feature to add extra security to your documents. 157 | 158 | # Backup 159 | 160 | Docker volumes are globally backed up using [borg-backup](../borg-backup). -------------------------------------------------------------------------------- /seafile/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | db: 5 | image: mariadb:10.5 6 | container_name: seafile-mysql 7 | restart: unless-stopped 8 | volumes: 9 | - ./seafile-mysql/db:/var/lib/mysql 10 | environment: 11 | - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWD} # Requested, set the root's password of MySQL service. 12 | - MYSQL_LOG_CONSOLE=true 13 | networks: 14 | - seafile-net 15 | labels: 16 | # Watchtower Update 17 | - "com.centurylinklabs.watchtower.enable=true" 18 | 19 | memcached: 20 | image: memcached:latest 21 | container_name: seafile-memcached 22 | restart: unless-stopped 23 | entrypoint: memcached -m 256 24 | networks: 25 | - seafile-net 26 | labels: 27 | # Watchtower Update 28 | - "com.centurylinklabs.watchtower.enable=true" 29 | 30 | seafile: 31 | image: seafileltd/seafile-mc:latest 32 | container_name: seafile 33 | restart: unless-stopped 34 | volumes: 35 | - ./shared:/shared 36 | environment: 37 | - DB_HOST=db 38 | - DB_ROOT_PASSWD=${DB_ROOT_PASSWD} # Requested, the value shuold be root's password of MySQL service. 39 | - SEAFILE_ADMIN_EMAIL=${SEAFILE_ADMIN_EMAIL} # Specifies Seafile admin user, default is 'me@example.com'. 40 | - SEAFILE_ADMIN_PASSWORD=${SEAFILE_ADMIN_PASSWORD} # Specifies Seafile admin password, default is 'asecret'. 41 | - SEAFILE_SERVER_LETSENCRYPT=false # Whether to use https or not. 42 | - SEAFILE_SERVER_HOSTNAME=${TRAEFIK_SEAFILE} # Specifies your host name if https is enabled. 43 | - SEAFILE_SERVICE_URL=https://${TRAEFIK_SEAFILE} 44 | networks: 45 | - proxy 46 | - seafile-net 47 | depends_on: 48 | - db 49 | - memcached 50 | labels: 51 | - "traefik.enable=true" 52 | - "traefik.http.routers.seafile.rule=Host(`${TRAEFIK_SEAFILE}`)" 53 | - "traefik.http.routers.seafile.entrypoints=https" 54 | - "traefik.http.routers.seafile.tls=true" 55 | - "traefik.http.routers.seafile.tls.certresolver=mydnschallenge" 56 | # Watchtower Update 57 | - "com.centurylinklabs.watchtower.enable=true" 58 | # Ip filtering 59 | - "traefik.http.routers.seafile.middlewares=whitelist@file" 60 | 61 | networks: 62 | seafile-net: 63 | proxy: 64 | external: true -------------------------------------------------------------------------------- /synapse-element/.env: -------------------------------------------------------------------------------- 1 | TRAEFIK_MATRIX=matrix.example.com 2 | TRAEFIK_ELEMENT=element.example.com -------------------------------------------------------------------------------- /synapse-element/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | matrix 5 |                 6 | pihole 7 |

8 | 9 | Matrix is an open standard for decentralised communication, which securely distributes persistent chatrooms over an open federation of servers preventing any single points of control or failure. 10 | 11 | Synapse is a Matrix "homeserver" implementation developed by the matrix.org core team. 12 | 13 | Element is a Matrix web client built using the Matrix React SDK. 14 | 15 | * Synapse 16 | * [Github](https://github.com/matrix-org/synapse) 17 | * [Documentation](https://matrix-org.github.io/synapse/latest/) 18 | * [Docker Image](https://hub.docker.com/r/matrixdotorg/synapse) 19 | 20 | * Element 21 | * [Github](https://github.com/vector-im/element-web) 22 | * [Docker Image](https://hub.docker.com/r/vectorim/element-web) 23 | 24 | # Table of Contents 25 | 26 | 27 | 28 | - [About](#about) 29 | - [Table of Contents](#table-of-contents) 30 | - [Files structure](#files-structure) 31 | - [Information](#information) 32 | - [docker-compose](#docker-compose) 33 | - [Usage](#usage) 34 | - [Requirements](#requirements) 35 | - [Configuration](#configuration) 36 | - [Update](#update) 37 | - [Security](#security) 38 | - [Backup](#backup) 39 | 40 | 41 | 42 | 43 | # Files structure 44 | 45 | ```bash 46 | . 47 | |-- docker-compose.yml 48 | |-- matrix-data/ 49 | |-- element-web/config.json 50 | ``` 51 | 52 | - `docker-compose.yml` - a docker-compose file, use to configure your application’s services 53 | - `matrix-data/` - a directory used to store the matrix data 54 | - `element-web/config.json` - a file used to store element's data 55 | 56 | Please make sure that all the files and directories are present. 57 | 58 | # Information 59 | 60 | ## docker-compose 61 | Links to the following [docker-compose.yml](docker-compose.yml). 62 | 63 | * docker-compose.yml 64 | ```yaml 65 | version: '3' 66 | 67 | services: 68 | 69 | synapse: 70 | image: matrixdotorg/synapse:latest 71 | restart: unless-stopped 72 | container_name: synapse 73 | environment: 74 | - SYNAPSE_LOG_LEVEL=INFO 75 | volumes: 76 | - ./matrix-data:/data 77 | labels: 78 | - "traefik.enable=true" 79 | - "traefik.http.routers.synapse.rule=Host(`${TRAEFIK_MATRIX}`)" 80 | - "traefik.http.routers.synapse.entrypoints=https" 81 | - "traefik.http.routers.synapse.tls=true" 82 | - "traefik.http.routers.synapse.tls.certresolver=mydnschallenge" 83 | 84 | # Watchtower Update 85 | - "com.centurylinklabs.watchtower.enable=true" 86 | networks: 87 | - proxy 88 | 89 | element: 90 | image: vectorim/element-web:latest 91 | restart: unless-stopped 92 | container_name: element 93 | depends_on: 94 | - synapse 95 | volumes: 96 | - ./element-web/config.json:/app/config.json:ro 97 | labels: 98 | - "traefik.enable=true" 99 | - "traefik.http.routers.element.rule=Host(`${TRAEFIK_ELEMENT}`)" 100 | - "traefik.http.routers.element.entrypoints=https" 101 | - "traefik.http.routers.element.tls=true" 102 | - "traefik.http.routers.element.tls.certresolver=mydnschallenge" 103 | 104 | # Watchtower Update 105 | - "com.centurylinklabs.watchtower.enable=true" 106 | networks: 107 | - proxy 108 | 109 | 110 | networks: 111 | proxy: 112 | external: true 113 | ``` 114 | * .env 115 | ```ini 116 | TRAEFIK_MATRIX=matrix.example.com 117 | TRAEFIK_ELEMENT=element.example.com 118 | ``` 119 | 120 | 121 | # Usage 122 | 123 | ## Requirements 124 | - [Traefik up and running](../traefik). 125 | - Subdomains of your choice, this example uses `element` and `matrix`. 126 | - You should be able to create a subdomain with your DNS provider, use a `A record` with the same IP address as your root domain. 127 | 128 | ## Configuration 129 | 130 | Check that the URL is correct in `element-web/config.json` and replace the environment variables in `.env` with your own. 131 | 132 | The first step is to generate a valid config file. To do this, you can run the image with the generate command line option. Please replace the `SYNAPSE_SERVER_NAME` with your own. 133 | 134 | ```bash 135 | sudo docker run -it --rm \ 136 | -v "$(pwd)/matrix-data:/data" \ 137 | -e SYNAPSE_SERVER_NAME=matrix.example.com \ 138 | -e SYNAPSE_REPORT_STATS=no \ 139 | matrixdotorg/synapse:latest generate 140 | ``` 141 | 142 | You can now start the service with : 143 | 144 | ```bash 145 | sudo docker-compose up -d 146 | ``` 147 | 148 | You can check that the matrix server is working by accessing the URL. You should then be able to access the element web-ui and create a new account. By default, the registration is disabled, change the `enable_registration` value to `true` in `matrix-data/homeserver.yaml`, then restart the container. 149 | 150 | # Update 151 | 152 | The image is automatically updated with [watchtower](../watchtower) thanks to the following label : 153 | 154 | ```yaml 155 | # Watchtower Update 156 | - "com.centurylinklabs.watchtower.enable=true" 157 | ``` 158 | 159 | # Security 160 | 161 | You can modify the matrix config file to increase security : `matrix-data/homeserver.yaml`. 162 | After you have created your account, you can disable registration with `enable_registration: false`. 163 | 164 | 165 | 166 | # Backup 167 | 168 | Docker volumes are globally backed up using [borg-backup](../borg-backup). -------------------------------------------------------------------------------- /synapse-element/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | 5 | synapse: 6 | image: matrixdotorg/synapse:latest 7 | restart: unless-stopped 8 | container_name: synapse 9 | environment: 10 | - SYNAPSE_LOG_LEVEL=INFO 11 | volumes: 12 | - ./matrix-data:/data 13 | labels: 14 | - "traefik.enable=true" 15 | - "traefik.http.routers.synapse.rule=Host(`${TRAEFIK_MATRIX}`)" 16 | - "traefik.http.routers.synapse.entrypoints=https" 17 | - "traefik.http.routers.synapse.tls=true" 18 | - "traefik.http.routers.synapse.tls.certresolver=mydnschallenge" 19 | 20 | # Watchtower Update 21 | - "com.centurylinklabs.watchtower.enable=true" 22 | networks: 23 | - proxy 24 | 25 | element: 26 | image: vectorim/element-web:latest 27 | restart: unless-stopped 28 | container_name: element 29 | depends_on: 30 | - synapse 31 | volumes: 32 | - ./element-web/config.json:/app/config.json:ro 33 | labels: 34 | - "traefik.enable=true" 35 | - "traefik.http.routers.element.rule=Host(`${TRAEFIK_ELEMENT}`)" 36 | - "traefik.http.routers.element.entrypoints=https" 37 | - "traefik.http.routers.element.tls=true" 38 | - "traefik.http.routers.element.tls.certresolver=mydnschallenge" 39 | 40 | # Watchtower Update 41 | - "com.centurylinklabs.watchtower.enable=true" 42 | networks: 43 | - proxy 44 | 45 | 46 | networks: 47 | proxy: 48 | external: true -------------------------------------------------------------------------------- /synapse-element/element-web/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "default_server_config": { 3 | "m.homeserver": { 4 | "base_url": "https://matrix.example.com", 5 | "server_name": "example.com" 6 | }, 7 | "m.identity_server": { 8 | "base_url": "https://vector.im" 9 | } 10 | }, 11 | "disable_custom_urls": false, 12 | "disable_guests": false, 13 | "disable_login_language_selector": false, 14 | "disable_3pid_login": false, 15 | "brand": "2li Matrix", 16 | "integrations_ui_url": "https://scalar.vector.im/", 17 | "integrations_rest_url": "https://scalar.vector.im/api", 18 | "integrations_jitsi_widget_url": "https://scalar.vector.im/api/widgets/jitsi.html", 19 | "bug_report_endpoint_url": "https://riot.im/bugreports/submit", 20 | "defaultCountryCode": "GB", 21 | "showLabsSettings": false, 22 | "features": { 23 | "feature_pinning": "labs", 24 | "feature_custom_status": "labs", 25 | "feature_custom_tags": "labs", 26 | "feature_state_counters": "labs" 27 | }, 28 | "default_federate": true, 29 | "default_theme": "light" 30 | } -------------------------------------------------------------------------------- /traefik/.env: -------------------------------------------------------------------------------- 1 | # DOMAIN.TLD = example.com 2 | DOMAIN=example 3 | TLD=com 4 | 5 | # DNS challenge credentials - will not be the same if you are using another provider 6 | OVH_ENDPOINT=xxxxxxxxxxxxxxxxxxxxxxx 7 | OVH_APPLICATION_KEY=xxxxxxxxxxxxxxxxxxxxxxx 8 | OVH_APPLICATION_SECRET=xxxxxxxxxxxxxxxxxxxxxxx 9 | OVH_CONSUMER_KEY=xxxxxxxxxxxxxxxxxxxxxxx -------------------------------------------------------------------------------- /traefik/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | Traefik 5 |

6 | 7 | Traefik is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. 8 | It is an Edge Router, it means that it's the door to your platform, and that it intercepts and routes every incoming request. 9 | 10 | * [Github](https://github.com/traefik/traefik/) 11 | * [Documentation](https://doc.traefik.io/traefik/) 12 | * [Docker Image](https://hub.docker.com/_/traefik) 13 | 14 | Traefik is a key component for this selfhosted infrastructure, it is providing the following features : 15 | 16 | - Act as a reverse proxy, enabling you to self-hosted multiple services behind a single IP 17 | - HTTPS for your services by leveraging Let's Encrypt 18 | - Easily configure TLS for all services 19 | - Use a whitelist to restrict services to a fix set of IPs 20 | 21 | 22 | # Table of Contents 23 | 24 | 25 | 26 | - [About](#about) 27 | - [Table of Contents](#table-of-contents) 28 | - [Files structure](#files-structure) 29 | - [Information](#information) 30 | - [docker-compose](#docker-compose) 31 | - [socket-proxy](#socket-proxy) 32 | - [traefik](#traefik) 33 | - [DNS Challenge with Let's Encrypt](#dns-challenge-with-lets-encrypt) 34 | - [Global redirect to HTTPS](#global-redirect-to-https) 35 | - [Redirect root to www](#redirect-root-to-www) 36 | - [Usage](#usage) 37 | - [Requirements](#requirements) 38 | - [Configuration](#configuration) 39 | - [Note](#note) 40 | - [Update](#update) 41 | - [Security](#security) 42 | - [Backup](#backup) 43 | 44 | 45 | 46 | # Files structure 47 | 48 | ```bash 49 | . 50 | |-- .env 51 | |-- docker-compose.yml 52 | |-- letsencrypt/ 53 | |-- rules/ 54 | | |-- tls.yml 55 | | `-- whitelist.yml 56 | `-- traefik.yml 57 | ``` 58 | 59 | - `.env` - a file containing all the environment variables used in the docker-compose.yml 60 | - `docker-compose.yml` - a docker-compose file, use to configure your application’s services 61 | - `letsencrypt/` - a directory used to store the certificates' information 62 | - `rules/` - a directory used to store traefik optional rules (TLS, IP whitelist) 63 | - `traefik.yml` - traefik configuration file 64 | 65 | Please make sure that all the files and directories are present. 66 | 67 | # Information 68 | 69 | Traefik has multiple ways to be configured, I will be using two of them for this guide : 70 | - Configuration file : Such as traefik.yml, tls.yml, ... 71 | - Labels : Used in a docker-compose file 72 | 73 | The configuration could be done using only one of the two method, but I find it easy to use files for standard configurations that should almost never change and labels to allow a more dynamic configuration. 74 | 75 | ## docker-compose 76 | Links to the following [docker-compose.yml](docker-compose.yml) and the corresponding [.env](.env). 77 | 78 | * docker-compose.yml 79 | ```yaml 80 | version: "3" 81 | 82 | services: 83 | traefik: 84 | image: "traefik:latest" 85 | container_name: "traefik" 86 | restart: unless-stopped 87 | depends_on: 88 | - socket-proxy 89 | ports: 90 | - "80:80" 91 | - "443:443" 92 | volumes: 93 | - "./traefik.yml:/traefik.yml:ro" 94 | - "./rules:/rules:ro" 95 | - "./letsencrypt:/letsencrypt" 96 | environment: 97 | - OVH_ENDPOINT=${OVH_ENDPOINT} 98 | - OVH_APPLICATION_KEY=${OVH_APPLICATION_KEY} 99 | - OVH_APPLICATION_SECRET=${OVH_APPLICATION_SECRET} 100 | - OVH_CONSUMER_KEY=${OVH_CONSUMER_KEY} 101 | networks: 102 | - proxy 103 | labels: 104 | - "traefik.enable=true" 105 | 106 | # global redirect to https 107 | - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)" 108 | - "traefik.http.routers.http-catchall.entrypoints=http" 109 | - "traefik.http.routers.http-catchall.middlewares=redirect-to-https" 110 | 111 | # middleware redirect 112 | - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" 113 | - "traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true" 114 | 115 | # redirect root to www 116 | - "traefik.http.routers.root.rule=host(`example.com`)" 117 | - "traefik.http.routers.root.entrypoints=https" 118 | - "traefik.http.routers.root.middlewares=redirect-root-to-www" 119 | - "traefik.http.routers.root.tls=true" 120 | 121 | # middleware redirect root to www 122 | - "traefik.http.middlewares.redirect-root-to-www.redirectregex.regex=^https://example\\.com/(.*)" 123 | - "traefik.http.middlewares.redirect-root-to-www.redirectregex.replacement=https://www.example.com/$${1}" 124 | 125 | # Watchtower Update 126 | - "com.centurylinklabs.watchtower.enable=true" 127 | 128 | socket-proxy: 129 | image: tecnativa/docker-socket-proxy 130 | container_name: traefik-socket-proxy 131 | restart: unless-stopped 132 | volumes: 133 | - /var/run/docker.sock:/var/run/docker.sock:ro 134 | environment: 135 | CONTAINERS: 1 136 | networks: 137 | - proxy 138 | labels: 139 | # Watchtower Update 140 | - "com.centurylinklabs.watchtower.enable=true" 141 | 142 | networks: 143 | proxy: 144 | external: true 145 | ``` 146 | * .env 147 | ```ini 148 | # DOMAIN.TLD = example.com 149 | DOMAIN=example 150 | TLD=com 151 | 152 | # DNS challenge credentials - will not be the same if you are using another provider 153 | OVH_ENDPOINT=xxxxxxxxxxxxxxxxxxxxxxx 154 | OVH_APPLICATION_KEY=xxxxxxxxxxxxxxxxxxxxxxx 155 | OVH_APPLICATION_SECRET=xxxxxxxxxxxxxxxxxxxxxxx 156 | OVH_CONSUMER_KEY=xxxxxxxxxxxxxxxxxxxxxxx 157 | ``` 158 | 159 | The docker-compose contains two services : 160 | - socket-proxy : This ensures Docker’s socket file to not be exposed to the public 161 | - traefik : Traefik application configuration 162 | 163 | ## socket-proxy 164 | 165 | The socket-proxy service is used to protect the docker socket, allowing Traefik unrestricted access to your Docker socket file could result in a vulnerability to the host computer, as per [Traefik own documentation](https://doc.traefik.io/traefik/providers/docker/#docker-api-access), should any other part of the Traefik container ever be compromised. 166 | 167 | Instead of allowing Traefik container full access to the Docker socket file, we can instead proxy only the API calls we need with [Tecnativa’s Docker Socket Proxy](https://github.com/Tecnativa/docker-socket-proxy), following the [principle of the least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege). 168 | 169 | ## traefik 170 | 171 | ### DNS Challenge with Let's Encrypt 172 | 173 | Traefik can use an ACME provider (like Let's Encrypt) for automatic certificate generation. It will create the certificate and attempt to renew it automatically 30 days before expiration. One of the great benefit of using DNS challenges is that it will allow us to use wildcard certificates, on the other hand, it can create a security risk as it requires giving rights to Traefik to create and remove some DNS records. 174 | 175 | For the DNS challenge, you'll need a [working provider](https://doc.traefik.io/traefik/https/acme/#providers) along with the credentials allowing to create and remove DNS records, 176 | If you are using OVH, you can use this [guide](https://medium.com/nephely/configure-traefik-for-the-dns-01-challenge-with-ovh-as-dns-provider-c737670c0434) to retrieve the credentials. 177 | 178 | 179 | ### Global redirect to HTTPS 180 | 181 | ```yaml 182 | # global redirect to https 183 | - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)" 184 | - "traefik.http.routers.http-catchall.entrypoints=http" 185 | - "traefik.http.routers.http-catchall.middlewares=redirect-to-https" 186 | ``` 187 | This rule will match all the HTTP requests and redirect them to HTTPS. It uses the redirect-to-https middleware. 188 | 189 | ### Redirect root to www 190 | 191 | ```yaml 192 | # redirect root to www 193 | - "traefik.http.routers.root.rule=host(`example.com`)" 194 | - "traefik.http.routers.root.entrypoints=https" 195 | - "traefik.http.routers.root.middlewares=redirect-root-to-www" 196 | - "traefik.http.routers.root.tls=true" 197 | ``` 198 | This rule will automatically redirect the root domain `example.com` to `www.example.com`. You can use the [webserver](../webserver) example to set up a website using docker. 199 | 200 | # Usage 201 | 202 | ## Requirements 203 | - A domain, we will use example.com for this guide. 204 | - DNS manager, usually it goes with the provider you used for your domain. We will use OVH for the guide. List of compatible [providers](https://doc.traefik.io/traefik/https/acme/#providers). 205 | - Ports 80 and 443 open, check your firewall. 206 | 207 | 208 | ## Configuration 209 | Before using the docker-compose file, please update the following configurations. 210 | 211 | - **change the domain** : The current domain is example.com, change it to your domain. The change need to be made in `.env` and `traefik.yml`
212 | ```bash 213 | DOMAIN=example 214 | TLD=com 215 | sed -i -e "s/example/'$DOMAIN'/g" .env 216 | sed -i -e "s/com/'$TLD'/g" .env 217 | sed -i -e "s/example.com/'$DOMAIN'.'$TLD'/g" traefik.yml 218 | ``` 219 | 220 | - **change the dns provider credentials** : Replace the provider name in `traefik.yml` if you are not using ovh. Replace the environment variables in `.env` and in `docker-compose.yml`. The example uses OVH but it can work with other providers, such as GoDaddy :
221 | - Get the [required settings](https://go-acme.github.io/lego/dns/godaddy/) and update the `.env` file 222 | ```bash 223 | # DNS challenge credentials 224 | GODADDY_API_KEY=xxxxx 225 | GODADDY_API_SECRET=xxxxx 226 | ``` 227 | - This is the only case where you are going to have to modify the docker-compose 228 | ```yaml 229 | environment: 230 | - GODADDY_API_KEY${GODADDY_API_KEY} 231 | - GODADDY_API_SECRET=${GODADDY_API_SECRET} 232 | ``` 233 | 234 | - **create the docker network** : As our services are split in multiple docker-compose, we need a network so that traefik can forward the requests.
235 | ```bash 236 | sudo docker network create proxy 237 | ``` 238 | 239 | - **update the whitelist (optional)** : Replace the IP address in `rules/whitelist.yml`. Use the IP address as well as the [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing). Whitelist is disable by default with `0.0.0.0/0`. The whitelist will be used on containers setting the following label.
240 | ```yaml 241 | # Ip filtering 242 | - "traefik.http.routers.service-router-name.middlewares=whitelist@file" 243 | ``` 244 | You can use the private IP address range used by docker (172.16.0.0/12) if you are using [wireguard](../wireguard-pihole-unbound). Then your services will only be available through your VPN (recommend for a better security). 245 | 246 | You can now run : 247 | 248 | ```bash 249 | sudo docker-compose up -d 250 | ``` 251 | To check the logs : 252 | 253 | ```bash 254 | sudo docker logs traefik 255 | ``` 256 | 257 | Traefik should be up and running ! To test if everything is running smoothly, you can try and use the [webserver](../webserver) service, it is a simple apache webserver showing `Hello World`. 258 | Keep in mind that traefik can take a little time to generate the first certificate, usually a couple of minutes. 259 | 260 | ## Note 261 | 262 | If you want to use the [Redirect root to www](#redirect-root-to-www) fonctionnality, you also need to have a certificate generated for your root domain. In order to do so, you will need to use a service which uses the root domain. 263 | The simplest way to do that is by running the [webserver](../webserver) service with the root domain. It only needs to be done once, you should then be able to see the entry in `letsencrypt/acme.json`, it will then be renewed automaticaly by traefik. 264 | 265 | # Update 266 | 267 | Both `traefik` and `socket-proxy` images are automatically updated with [watchtower](../watchtower) thanks to the following label : 268 | 269 | ```yaml 270 | # Watchtower Update 271 | - "com.centurylinklabs.watchtower.enable=true" 272 | ``` 273 | 274 | 275 | # Security 276 | 277 | The socket-proxy service is used to protect the docker socket. 278 | 279 | # Backup 280 | 281 | Docker volumes are globally backed up using [borg-backup](../borg-backup). -------------------------------------------------------------------------------- /traefik/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | traefik: 5 | image: "traefik:latest" 6 | container_name: "traefik" 7 | restart: unless-stopped 8 | depends_on: 9 | - socket-proxy 10 | ports: 11 | - "80:80" 12 | - "443:443" 13 | volumes: 14 | - "./traefik.yml:/traefik.yml:ro" 15 | - "./rules:/rules:ro" 16 | - "./letsencrypt:/letsencrypt" 17 | environment: 18 | - OVH_ENDPOINT=${OVH_ENDPOINT} 19 | - OVH_APPLICATION_KEY=${OVH_APPLICATION_KEY} 20 | - OVH_APPLICATION_SECRET=${OVH_APPLICATION_SECRET} 21 | - OVH_CONSUMER_KEY=${OVH_CONSUMER_KEY} 22 | networks: 23 | - proxy 24 | labels: 25 | - "traefik.enable=true" 26 | 27 | # global redirect to https 28 | - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)" 29 | - "traefik.http.routers.http-catchall.entrypoints=http" 30 | - "traefik.http.routers.http-catchall.middlewares=redirect-to-https" 31 | 32 | # middleware redirect 33 | - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" 34 | - "traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true" 35 | 36 | # redirect root to www 37 | - "traefik.http.routers.root.rule=host(`${DOMAIN}.${TLD}`)" 38 | - "traefik.http.routers.root.entrypoints=https" 39 | - "traefik.http.routers.root.middlewares=redirect-root-to-www" 40 | - "traefik.http.routers.root.tls=true" 41 | 42 | # middleware redirect root to www 43 | - "traefik.http.middlewares.redirect-root-to-www.redirectregex.regex=^https://${DOMAIN}\\.${TLD}/(.*)" 44 | - "traefik.http.middlewares.redirect-root-to-www.redirectregex.replacement=https://www.${DOMAIN}.${TLD}/$${1}" 45 | 46 | # Watchtower Update 47 | - "com.centurylinklabs.watchtower.enable=true" 48 | 49 | socket-proxy: 50 | image: tecnativa/docker-socket-proxy 51 | container_name: traefik-socket-proxy 52 | restart: unless-stopped 53 | volumes: 54 | - /var/run/docker.sock:/var/run/docker.sock:ro 55 | environment: 56 | CONTAINERS: 1 57 | networks: 58 | - proxy 59 | labels: 60 | # Watchtower Update 61 | - "com.centurylinklabs.watchtower.enable=true" 62 | 63 | networks: 64 | proxy: 65 | external: true -------------------------------------------------------------------------------- /traefik/rules/tls.yml: -------------------------------------------------------------------------------- 1 | tls: 2 | options: 3 | TLSv13: 4 | minVersion: VersionTLS13 5 | cipherSuites: 6 | - TLS_AES_256_GCM_SHA384 7 | - TLS_CHACHA20_POLY1305_SHA256 8 | sniStrict: true 9 | 10 | default: 11 | minVersion: VersionTLS12 12 | cipherSuites: 13 | - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 14 | - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 15 | sniStrict: true -------------------------------------------------------------------------------- /traefik/rules/whitelist.yml: -------------------------------------------------------------------------------- 1 | http: 2 | middlewares: 3 | whitelist: 4 | ipWhiteList: 5 | sourceRange: 6 | - "0.0.0.0/0" 7 | # Private IP range use by docker, enable to enable services access through VPN 8 | #- "172.16.0.0/12" -------------------------------------------------------------------------------- /traefik/traefik.yml: -------------------------------------------------------------------------------- 1 | entryPoints: 2 | http: 3 | address: ":80" 4 | 5 | https: 6 | address: ":443" 7 | 8 | providers: 9 | docker: 10 | endpoint: "tcp://socket-proxy:2375" 11 | exposedByDefault: false 12 | 13 | file: 14 | directory: /rules 15 | watch: true 16 | 17 | certificatesResolvers: 18 | mydnschallenge: 19 | acme: 20 | email: mail@example.com 21 | storage: ./letsencrypt/acme.json 22 | dnsChallenge: 23 | provider: ovh 24 | delayBeforeCheck: 10 25 | 26 | log: 27 | level: INFO -------------------------------------------------------------------------------- /transmission/.env: -------------------------------------------------------------------------------- 1 | TRAEFIK_TRANSMISSION=transmission.example.com 2 | TZ=Europe/Paris 3 | WEB_USER=xxxxxxxxxxxxxxx 4 | WEB_PASS=xxxxxxxxxxxxxxx 5 | 6 | # user PUID and group PGID - can be found by running id your-user 7 | PUID=1000 8 | PGID=1000 -------------------------------------------------------------------------------- /transmission/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | transmission 5 |

6 | 7 | Transmission is a fast, easy, and free BitTorrent client. 8 | 9 | * [Github](https://github.com/transmission/transmission) 10 | * [website](https://transmissionbt.com/) 11 | * [Docker Image](https://hub.docker.com/r/linuxserver/transmission) 12 | 13 | # Table of Contents 14 | 15 | 16 | 17 | - [About](#about) 18 | - [Table of Contents](#table-of-contents) 19 | - [Information](#information) 20 | - [docker-compose](#docker-compose) 21 | - [Usage](#usage) 22 | - [Requirements](#requirements) 23 | - [Configuration](#configuration) 24 | - [Update](#update) 25 | - [Backup](#backup) 26 | 27 | 28 | 29 | ```bash 30 | . 31 | |-- .env 32 | |-- data/ 33 | `-- docker-compose.yml 34 | ``` 35 | 36 | * `.env` - a file containing all the environment variables used in the docker-compose.yml 37 | * `docker-compose.yml` - a docker-compose file, use to configure your application’s services 38 | * `data/` - a directory used to store the data 39 | 40 | Please make sure that all the files and directories are present. 41 | 42 | # Information 43 | 44 | ## docker-compose 45 | 46 | Links to the following [docker-compose.yml](docker-compose.yml) and the corresponding [.env](.env). 47 | 48 | * docker-compose.yml 49 | ```yaml 50 | vversion: '3' 51 | 52 | services: 53 | transmission: 54 | image: 'linuxserver/transmission:latest' 55 | container_name: transmission 56 | restart: unless-stopped 57 | volumes: 58 | - ./data/config:/config 59 | - ./data/downloads:/downloads 60 | - ./data/watch:/watch 61 | environment: 62 | - PUID=${PUID} 63 | - PGID=${PGID} 64 | - TZ=${TZ} 65 | - USER=${WEB_USER} 66 | - PASS=${WEB_PASS} 67 | ports: 68 | - 51413:51413 69 | - 51413:51413/udp 70 | networks: 71 | - proxy 72 | labels: 73 | - "traefik.enable=true" 74 | - "traefik.http.routers.transmission.rule=Host(`${TRAEFIK_TRANSMISSION}`)" 75 | - "traefik.http.routers.transmission.entrypoints=https" 76 | - "traefik.http.routers.transmission.tls=true" 77 | - "traefik.http.routers.transmission.tls.certresolver=mydnschallenge" 78 | - "traefik.http.services.transmission.loadbalancer.server.port=9091" 79 | # Watchtower Update 80 | - "com.centurylinklabs.watchtower.enable=true" 81 | 82 | networks: 83 | proxy: 84 | external: true 85 | ``` 86 | * .env 87 | ``` 88 | TRAEFIK_TRANSMISSION=transmission.example.com 89 | TZ=Europe/Paris 90 | WEB_USER=xxxxxxxxxxxxxxx 91 | WEB_PASS=xxxxxxxxxxxxxxx 92 | 93 | # user PUID and group PGID - can be found by running id your-user 94 | PUID=1000 95 | PGID=1000 96 | ``` 97 | 98 | The docker-compose contains only one service using the transmission image. 99 | 100 | # Usage 101 | 102 | ## Requirements 103 | 104 | * [Traefik up and running](../traefik). 105 | * A subdomain of your choice, this example uses `transmission`. 106 | * You should be able to create a subdomain with your DNS provider, use a `A record` with the same IP address as your root domain. 107 | * Port 51413 open, check your firewall. 108 | 109 | ## Configuration 110 | 111 | The linuxserver images are using the PUID and PGID, they allow the container to map the container's internal user to a user on the host machine, more information [here](https://docs.linuxserver.io/general/understanding-puid-and-pgid). 112 | 113 | To find yours, use `id user`. Replace the environment variables in `.env` with your own, then run : 114 | 115 | ```bash 116 | sudo docker-compose up -d 117 | ``` 118 | 119 | # Update 120 | 121 | The image is automatically updated with [watchtower](../watchtower) thanks to the following label : 122 | 123 | ```yaml 124 | # Watchtower Update 125 | - "com.centurylinklabs.watchtower.enable=true" 126 | ``` 127 | 128 | # Backup 129 | 130 | Docker volumes are globally backed up using [borg-backup](../borg-backup). 131 | 132 | You may want to exclude the downloads folder from the backups, add the following to [`borg-backup/excludes.txt`](../borg-backup/excludes.txt): 133 | ``` 134 | /full/path/to/transmission/data/downloads 135 | ``` 136 | -------------------------------------------------------------------------------- /transmission/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | transmission: 5 | image: 'linuxserver/transmission:latest' 6 | container_name: transmission 7 | restart: unless-stopped 8 | volumes: 9 | - ./data/config:/config 10 | - ./data/downloads:/downloads 11 | - ./data/watch:/watch 12 | environment: 13 | - PUID=${PUID} 14 | - PGID=${PGID} 15 | - TZ=${TZ} 16 | - USER=${WEB_USER} 17 | - PASS=${WEB_PASS} 18 | ports: 19 | - 51413:51413 20 | - 51413:51413/udp 21 | networks: 22 | - proxy 23 | labels: 24 | - "traefik.enable=true" 25 | - "traefik.http.routers.transmission.rule=Host(`${TRAEFIK_TRANSMISSION}`)" 26 | - "traefik.http.routers.transmission.entrypoints=https" 27 | - "traefik.http.routers.transmission.tls=true" 28 | - "traefik.http.routers.transmission.tls.certresolver=mydnschallenge" 29 | - "traefik.http.services.transmission.loadbalancer.server.port=9091" 30 | # Watchtower Update 31 | - "com.centurylinklabs.watchtower.enable=true" 32 | 33 | networks: 34 | proxy: 35 | external: true -------------------------------------------------------------------------------- /trilium/.env: -------------------------------------------------------------------------------- 1 | TRAEFIK_TRILIUM=trilium.example.com -------------------------------------------------------------------------------- /trilium/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | trilium 5 |

6 | 7 | Trilium Notes is a hierarchical note-taking application with focus on building large personal knowledge bases 8 | 9 | * [Github](https://github.com/zadam/trilium) 10 | * [Documentation](https://github.com/zadam/trilium/wiki/) 11 | * [Docker Image](https://hub.docker.com/r/zadam/trilium) 12 | 13 | # Table of Contents 14 | 15 | 16 | 17 | - [About](#about) 18 | - [Table of Contents](#table-of-contents) 19 | - [Information](#information) 20 | - [docker-compose](#docker-compose) 21 | - [Usage](#usage) 22 | - [Requirements](#requirements) 23 | - [Configuration](#configuration) 24 | - [Update](#update) 25 | - [Backup](#backup) 26 | 27 | 28 | 29 | ```bash 30 | . 31 | |-- .env 32 | |-- data/ 33 | `-- docker-compose.yml 34 | ``` 35 | 36 | * `.env` - a file containing all the environment variables used in the docker-compose.yml 37 | * `docker-compose.yml` - a docker-compose file, use to configure your application’s services 38 | * `data/` - a directory used to store the data 39 | 40 | Please make sure that all the files and directories are present. 41 | 42 | # Information 43 | 44 | ## docker-compose 45 | 46 | Links to the following [docker-compose.yml](docker-compose.yml) and the corresponding [.env](.env). 47 | 48 | * docker-compose.yml 49 | ```yaml 50 | version: '3' 51 | 52 | services: 53 | trilium: 54 | image: 'zadam/trilium:latest' 55 | container_name: trilium 56 | restart: unless-stopped 57 | volumes: 58 | - "./data:/home/node/trilium-data" 59 | networks: 60 | - proxy 61 | labels: 62 | - "traefik.enable=true" 63 | - "traefik.http.routers.webserver.rule=Host(`${TRAEFIK_TRILIUM}`)" 64 | - "traefik.http.routers.webserver.entrypoints=https" 65 | - "traefik.http.routers.webserver.tls=true" 66 | - "traefik.http.routers.webserver.tls.certresolver=mydnschallenge" 67 | # Watchtower Update 68 | - "com.centurylinklabs.watchtower.enable=true" 69 | 70 | networks: 71 | proxy: 72 | external: true 73 | ``` 74 | * .env 75 | ``` 76 | TRAEFIK_TRILIUM=trilium.example.com 77 | ``` 78 | 79 | The docker-compose contains only one service using the trilium image. 80 | 81 | # Usage 82 | 83 | ## Requirements 84 | 85 | * [Traefik up and running](../traefik). 86 | * A subdomain of your choice, this example uses `trilium`. 87 | * You should be able to create a subdomain with your DNS provider, use a `A record` with the same IP address as your root domain. 88 | 89 | ## Configuration 90 | 91 | Replace the environment variables in `.env` with your own, then run : 92 | 93 | ```bash 94 | sudo docker-compose up -d 95 | ``` 96 | 97 | You should then be able to access the trilium web-ui and start creating notes ! 98 | 99 | # Update 100 | 101 | The image is automatically updated with [watchtower](../watchtower) thanks to the following label : 102 | 103 | ```yaml 104 | # Watchtower Update 105 | - "com.centurylinklabs.watchtower.enable=true" 106 | ``` 107 | 108 | # Backup 109 | 110 | Docker volumes are globally backed up using [borg-backup](../borg-backup). 111 | -------------------------------------------------------------------------------- /trilium/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | trilium: 5 | image: 'zadam/trilium:latest' 6 | container_name: trilium 7 | restart: unless-stopped 8 | volumes: 9 | - "./data:/home/node/trilium-data" 10 | networks: 11 | - proxy 12 | labels: 13 | - "traefik.enable=true" 14 | - "traefik.http.routers.trilium.rule=Host(`${TRAEFIK_TRILIUM}`)" 15 | - "traefik.http.routers.trilium.entrypoints=https" 16 | - "traefik.http.routers.trilium.tls=true" 17 | - "traefik.http.routers.trilium.tls.certresolver=mydnschallenge" 18 | # Watchtower Update 19 | - "com.centurylinklabs.watchtower.enable=true" 20 | 21 | networks: 22 | proxy: 23 | external: true -------------------------------------------------------------------------------- /vaultwarden/.env: -------------------------------------------------------------------------------- 1 | TRAEFIK_VAULTWARDEN=vaultwarden.example.com 2 | ADMIN_TOKEN=xxxxxxxxxxxxxxxxx -------------------------------------------------------------------------------- /vaultwarden/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | bitwarden 5 |

6 | 7 | Vaultwarden is an alternative implementation of the Bitwarden server API written in Rust and compatible with upstream Bitwarden clients, it is perfect for self-hosted deployment where running the official resource-heavy service might not be ideal. 8 | 9 | * [Github](https://github.com/dani-garcia/vaultwarden) 10 | * [Documentation](https://github.com/dani-garcia/vaultwarden/wiki) 11 | * [Docker Image](https://hub.docker.com/r/vaultwarden/server) 12 | 13 | Bitwarden is a free and open-source password management service that stores sensitive information such as website credentials in an encrypted vault. 14 | 15 | # Table of Contents 16 | 17 | 18 | 19 | - [About](#about) 20 | - [Table of Contents](#table-of-contents) 21 | - [Files structure](#files-structure) 22 | - [Information](#information) 23 | - [docker-compose](#docker-compose) 24 | - [Usage](#usage) 25 | - [Requirements](#requirements) 26 | - [Configuration](#configuration) 27 | - [Update](#update) 28 | - [Security](#security) 29 | - [Backup](#backup) 30 | 31 | 32 | 33 | # Files structure 34 | 35 | ```bash 36 | . 37 | |-- .env 38 | |-- data/ 39 | `-- docker-compose.yml 40 | ``` 41 | 42 | - `.env` - a file containing all the environment variables used in the docker-compose.yml 43 | - `docker-compose.yml` - a docker-compose file, use to configure your application’s services 44 | - `data/` - a directory used to store vaultwarden data 45 | 46 | Please make sure that all the files and directories are present. 47 | 48 | # Information 49 | 50 | ## docker-compose 51 | Links to the following [docker-compose.yml](docker-compose.yml) and the corresponding [.env](.env). 52 | 53 | * docker-compose.yml 54 | ```yaml 55 | version: "3" 56 | 57 | services: 58 | bitwardenrs: 59 | image: vaultwarden/server 60 | container_name: vaultwarden 61 | restart: unless-stopped 62 | volumes: 63 | - ./data:/data 64 | environment: 65 | - WEBSOCKET_ENABLED=true 66 | - WEB_VAULT_ENABLED=true 67 | - SIGNUPS_ALLOWED=false 68 | # Comment admin token to disable admin interface 69 | - ADMIN_TOKEN=${ADMIN_TOKEN} 70 | networks: 71 | - proxy 72 | labels: 73 | - "traefik.enable=true" 74 | - "traefik.http.routers.bitwarden.rule=Host(`${TRAEFIK_VAULTWARDEN}`)" 75 | - "traefik.http.routers.bitwarden.entrypoints=https" 76 | - "traefik.http.routers.bitwarden.tls=true" 77 | - "traefik.http.routers.bitwarden.tls.certresolver=mydnschallenge" 78 | # Watchtower Update 79 | - "com.centurylinklabs.watchtower.enable=true" 80 | # Ip filtering 81 | - "traefik.http.routers.bitwarden.middlewares=whitelist@file" 82 | logging: 83 | driver: "syslog" 84 | options: 85 | tag: "Bitwarden" 86 | 87 | networks: 88 | proxy: 89 | external: true 90 | ``` 91 | * .env 92 | ```ini 93 | TRAEFIK_VAULTWARDEN=vaultwarden.example.com 94 | ADMIN_TOKEN=xxxxxxxxxxxxxxxxx 95 | ``` 96 | 97 | # Usage 98 | 99 | ## Requirements 100 | - [Traefik up and running](../traefik). 101 | - A subdomain of your choice, this example uses `vaultwarden`. 102 | - You should be able to create a subdomain with your DNS provider, use a `A record` with the same IP address as your root domain. 103 | 104 | ## Configuration 105 | 106 | Replace the environment variable in `.env` with your own, then run : 107 | 108 | ```bash 109 | sudo docker-compose up -d 110 | ``` 111 | 112 | You should then be able to access the bitwarden web-ui admin interface with the ADMIN_TOKEN. 113 | 114 | # Update 115 | 116 | The image is automatically updated with [watchtower](../watchtower) thanks to the following label : 117 | 118 | ```yaml 119 | # Watchtower Update 120 | - "com.centurylinklabs.watchtower.enable=true" 121 | ``` 122 | 123 | # Security 124 | 125 | Comment admin token to disable the admin interface after you have created your users. 126 | The IP filtering label is set in the docker-compose, you can restrict access to this service by modifying the traefik [whitelist](traefik/rules/whitelist.yml). 127 | 128 | # Backup 129 | 130 | Docker volumes are globally backed up using [borg-backup](../borg-backup). -------------------------------------------------------------------------------- /vaultwarden/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | bitwardenrs: 5 | image: vaultwarden/server 6 | container_name: vaultwarden 7 | restart: unless-stopped 8 | volumes: 9 | - ./data:/data 10 | environment: 11 | - WEBSOCKET_ENABLED=true 12 | - WEB_VAULT_ENABLED=true 13 | - SIGNUPS_ALLOWED=false 14 | # Comment admin token to disable admin interface 15 | - ADMIN_TOKEN=${ADMIN_TOKEN} 16 | networks: 17 | - proxy 18 | labels: 19 | - "traefik.enable=true" 20 | - "traefik.http.routers.bitwarden.rule=Host(`${TRAEFIK_VAULTWARDEN}`)" 21 | - "traefik.http.routers.bitwarden.entrypoints=https" 22 | - "traefik.http.routers.bitwarden.tls=true" 23 | - "traefik.http.routers.bitwarden.tls.certresolver=mydnschallenge" 24 | # Watchtower Update 25 | - "com.centurylinklabs.watchtower.enable=true" 26 | # Ip filtering 27 | - "traefik.http.routers.bitwarden.middlewares=whitelist@file" 28 | logging: 29 | driver: "syslog" 30 | options: 31 | tag: "Bitwarden" 32 | 33 | networks: 34 | proxy: 35 | external: true -------------------------------------------------------------------------------- /watchtower/.env: -------------------------------------------------------------------------------- 1 | GOTIFY_URL=https://gotify.example.com/ 2 | GOTIFY_TOKEN=xxxxxxxxxxxxxxxxxx -------------------------------------------------------------------------------- /watchtower/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | watchtower 5 |

6 | 7 | Watchtower is a container-based solution for automating Docker container base image updates. It will pull down your new image, gracefully shut down your existing container and restart it with the same options that were used when it was deployed initially. 8 | 9 | * [Github](https://github.com/containrrr/watchtower) 10 | * [Documentation](https://containrrr.dev/watchtower/) 11 | * [Docker Image](https://hub.docker.com/r/containrrr/watchtower) 12 | 13 | # Table of Contents 14 | 15 | 16 | 17 | - [About](#about) 18 | - [Table of Contents](#table-of-contents) 19 | - [Files structure](#files-structure) 20 | - [Information](#information) 21 | - [docker-compose](#docker-compose) 22 | - [Usage](#usage) 23 | - [Configuration](#configuration) 24 | - [Update](#update) 25 | - [Security](#security) 26 | - [Backup](#backup) 27 | 28 | 29 | 30 | # Files structure 31 | 32 | ```bash 33 | . 34 | |-- .env 35 | `-- docker-compose.yml 36 | ``` 37 | 38 | - `.env` - a file containing all the environment variables used in the docker-compose.yml 39 | - `docker-compose.yml` - a docker-compose file, use to configure your application’s services 40 | 41 | Please make sure that all the files and directories are present. 42 | 43 | # Information 44 | 45 | The following docker-compose is configured to check for update every monday. If you are using the borg-backup [strategy](../borg-backup), everything will be backed-up before the image is updated to prevent data corruption. 46 | 47 | Watchtower if configured to automatically upgrade your images and to then, send you a notification with [gotify](../gotify). Everything can be changed by modifying the [environnement variables](https://containrrr.dev/watchtower/arguments/). 48 | 49 | If you want watchtower to only notify you and not upgrade the images, uncomment the following environnement variable in the docker-compose : `- WATCHTOWER_MONITOR_ONLY=true` 50 | 51 | ## docker-compose 52 | Links to the following [docker-compose.yml](docker-compose.yml) and the corresponding [.env](.env). 53 | 54 | * docker-compose.yml 55 | ```yaml 56 | version: "3" 57 | 58 | services: 59 | watchtower: 60 | image: containrrr/watchtower 61 | container_name: watchtower 62 | restart: unless-stopped 63 | volumes: 64 | - /var/run/docker.sock:/var/run/docker.sock 65 | environment: 66 | - WATCHTOWER_CLEANUP=true 67 | - WATCHTOWER_LABEL_ENABLE=true 68 | #- WATCHTOWER_MONITOR_ONLY=true 69 | #- WATCHTOWER_POLL_INTERVAL=30 70 | - WATCHTOWER_SCHEDULE=0 0 4 * * MON 71 | - WATCHTOWER_NOTIFICATIONS=gotify 72 | - WATCHTOWER_NOTIFICATION_GOTIFY_URL=${GOTIFY_URL} 73 | - WATCHTOWER_NOTIFICATION_GOTIFY_TOKEN=${GOTIFY_TOKEN} 74 | labels: 75 | - "com.centurylinklabs.watchtower.enable=true" 76 | ``` 77 | * .env 78 | ```ini 79 | # The gotify token can be configured in the gotify WebUI 80 | GOTIFY_URL=https://gotify.example.com/ 81 | GOTIFY_TOKEN=xxxxxxxxxxxxxxxxxx 82 | ``` 83 | 84 | # Usage 85 | 86 | ## Configuration 87 | 88 | If you don't want to use gotify for the notification, feel free to remove the environnement variables from both the `.env` and the `docker-compose.yml` file. 89 | 90 | Replace the environment variables in `.env` with your own, then run : 91 | 92 | ```bash 93 | sudo docker-compose up -d 94 | ``` 95 | 96 | Watchtower will then check for update every monday and send you a notification with gotify once an image is updated. 97 | 98 | # Update 99 | 100 | The image is automatically updated with [watchtower](../watchtower) thanks to the following label : 101 | 102 | ```yaml 103 | # Watchtower Update 104 | - "com.centurylinklabs.watchtower.enable=true" 105 | ``` 106 | 107 | # Security 108 | 109 | Automatically upgrading open-source images can be a huge security risk. The safest solution would be to only [monitor](https://containrrr.dev/watchtower/arguments/#without_updating_containers) the images and check the updated image before doing the upgrade. 110 | 111 | # Backup 112 | 113 | Backup are not required. -------------------------------------------------------------------------------- /watchtower/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | watchtower: 5 | image: containrrr/watchtower 6 | container_name: watchtower 7 | restart: unless-stopped 8 | volumes: 9 | - /var/run/docker.sock:/var/run/docker.sock 10 | environment: 11 | - WATCHTOWER_CLEANUP=true 12 | - WATCHTOWER_LABEL_ENABLE=true 13 | #- WATCHTOWER_MONITOR_ONLY=true 14 | #- WATCHTOWER_POLL_INTERVAL=30 15 | - WATCHTOWER_SCHEDULE=0 0 4 * * MON 16 | - WATCHTOWER_NOTIFICATIONS=gotify 17 | - WATCHTOWER_NOTIFICATION_GOTIFY_URL=${GOTIFY_URL} 18 | - WATCHTOWER_NOTIFICATION_GOTIFY_TOKEN=${GOTIFY_TOKEN} 19 | labels: 20 | - "com.centurylinklabs.watchtower.enable=true" -------------------------------------------------------------------------------- /webserver/.env: -------------------------------------------------------------------------------- 1 | TRAEFIK_WEBSERVER=www.example.com -------------------------------------------------------------------------------- /webserver/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | httpd 5 |

6 | 7 | The Apache HTTP Server Project is a collaborative software development effort aimed at creating a robust, commercial-grade, featureful, and freely-available source code implementation of an HTTP (Web) server. 8 | 9 | * [Github](https://github.com/apache/httpd) 10 | * [Documentation](https://httpd.apache.org/docs/current/) 11 | * [Docker Image](https://hub.docker.com/_/httpd) 12 | 13 | Use this service in combination with Traefik to host any custom-made website you want. Portofolio, resume, blog, ... 14 | 15 | The following example will host a simple Hello World website. 16 | 17 | # Table of Contents 18 | 19 | 20 | 21 | - [About](#about) 22 | - [Table of Contents](#table-of-contents) 23 | - [Files structure](#files-structure) 24 | - [Information](#information) 25 | - [docker-compose](#docker-compose) 26 | - [Usage](#usage) 27 | - [Requirements](#requirements) 28 | - [Configuration](#configuration) 29 | - [Update](#update) 30 | - [Backup](#backup) 31 | 32 | 33 | 34 | # Files structure 35 | 36 | ```bash 37 | . 38 | |-- data/ 39 | | `-- index.html 40 | `-- docker-compose.yml 41 | ``` 42 | 43 | - `docker-compose.yml` - a docker-compose file, use to configure your application’s services 44 | - `data/` - a directory used to store your website content 45 | 46 | Please make sure that all the files and directories are present. 47 | 48 | # Information 49 | 50 | In this example, the website will only display a Hello World as you can see in the [index.html](data/index.html). 51 | 52 | ## docker-compose 53 | Links to the following [docker-compose.yml](docker-compose.yml). 54 | 55 | * docker-compose.yml 56 | ```yaml 57 | version: '3' 58 | 59 | services: 60 | webserver: 61 | image: 'httpd:2.4' 62 | container_name: webserver 63 | restart: unless-stopped 64 | volumes: 65 | - ./data:/usr/local/apache2/htdocs/ 66 | networks: 67 | - proxy 68 | labels: 69 | - "traefik.enable=true" 70 | - "traefik.http.routers.webserver.rule=Host(`www.example.com`)" 71 | - "traefik.http.routers.webserver.entrypoints=https" 72 | - "traefik.http.routers.webserver.tls=true" 73 | - "traefik.http.routers.webserver.tls.certresolver=mydnschallenge" 74 | # Watchtower Update 75 | - "com.centurylinklabs.watchtower.enable=true" 76 | 77 | networks: 78 | proxy: 79 | external: true 80 | ``` 81 | * .env 82 | ```ini 83 | TRAEFIK_WEBSERVER=www.example.com 84 | ``` 85 | 86 | The docker-compose contains only one service using the apache httpd image. 87 | 88 | # Usage 89 | 90 | ## Requirements 91 | - [Traefik up and running](../traefik). 92 | - A subdomain of your choice, this example uses `www`. 93 | - You should be able to create a subdomain with your DNS provider, use a `A record` with the same IP address as your root domain. 94 | 95 | 96 | ## Configuration 97 | Before using the docker-compose file, please update the following configurations. 98 | 99 | - **change the domain** : The current domain is example.com, change it to your domain
100 | ```bash 101 | sed -i -e "s/www.example.com/www.your-domain.com/g" docker-compose.yml 102 | ``` 103 | 104 | - **change the content of the website (optional)** : Replace the content of `data` with your own website.
105 | 106 | You can now run : 107 | 108 | ```bash 109 | sudo docker-compose up -d 110 | ``` 111 | 112 | # Update 113 | 114 | The image is automatically updated with [watchtower](../watchtower) thanks to the following label : 115 | 116 | ```yaml 117 | # Watchtower Update 118 | - "com.centurylinklabs.watchtower.enable=true" 119 | ``` 120 | 121 | # Backup 122 | 123 | Docker volumes are globally backed up using [borg-backup](../borg-backup). -------------------------------------------------------------------------------- /webserver/data/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hi 5 | 6 | 7 |

Hello world !

8 | 9 | 10 | -------------------------------------------------------------------------------- /webserver/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | webserver: 5 | image: 'httpd:2.4' 6 | container_name: webserver 7 | restart: unless-stopped 8 | volumes: 9 | - ./data:/usr/local/apache2/htdocs/ 10 | networks: 11 | - proxy 12 | labels: 13 | - "traefik.enable=true" 14 | - "traefik.http.routers.webserver.rule=Host(`${TRAEFIK_WEBSERVER}`)" 15 | - "traefik.http.routers.webserver.entrypoints=https" 16 | - "traefik.http.routers.webserver.tls=true" 17 | - "traefik.http.routers.webserver.tls.certresolver=mydnschallenge" 18 | # Watchtower Update 19 | - "com.centurylinklabs.watchtower.enable=true" 20 | 21 | networks: 22 | proxy: 23 | external: true -------------------------------------------------------------------------------- /wireguard-pihole-unbound/.env: -------------------------------------------------------------------------------- 1 | SERVERURL=vpn.example.com 2 | TZ=Europe/Paris 3 | 4 | # How many peers to generate for you (clients) 5 | PEERS=2 6 | 7 | # user PUID and group PGID - can be found by running id your-user 8 | PUID=1000 9 | PGID=1000 -------------------------------------------------------------------------------- /wireguard-pihole-unbound/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | wireguard 5 |                    6 | pihole 7 |                    8 | unbound 9 |

10 | 11 | Wireguard is a virtual private network (VPN), it provides you a secure, encrypted tunnel for online traffic and allow you to manage a remote private network. 12 | Pihole is a DNS sinkhole that protects your devices from unwanted content without installing any client-side software. Unbound is a validating, recursive, caching DNS resolver. 13 | 14 | * Wireguard 15 | * [Github](https://github.com/WireGuard) 16 | * [Documentation](https://www.wireguard.com/quickstart/) 17 | * [Docker Image](https://hub.docker.com/r/linuxserver/wireguard) 18 | 19 | * Pi-Hole 20 | * [Github](https://github.com/pi-hole/pi-hole) 21 | * [Documentation](https://docs.pi-hole.net/) 22 | * [Docker Image](https://hub.docker.com/r/pihole/pihole) 23 | 24 | * Unbound 25 | * [Github](https://github.com/NLnetLabs/unbound) 26 | * [Documentation](https://unbound.docs.nlnetlabs.nl/en/latest/) 27 | * [Docker Image](https://hub.docker.com/r/mvance/unbound) 28 | 29 | This guide combine the three services so that every device that are connected to the VPN also pass through pihole and unbound. Having a VPN will also reinforce security for your overall infrastructure as you can combine it with [traefik IP whitelist](../traefik#Configuration). 30 | 31 | Credits to [@IAmStoxe](https://github.com/IAmStoxe/wirehole). 32 | 33 | # Table of Contents 34 | 35 | 36 | 37 | - [About](#about) 38 | - [Table of Contents](#table-of-contents) 39 | - [Files structure](#files-structure) 40 | - [Information](#information) 41 | - [docker-compose](#docker-compose) 42 | - [Usage](#usage) 43 | - [Requirements](#requirements) 44 | - [Configuration](#configuration) 45 | - [Wireguard](#wireguard) 46 | - [Pihole](#pihole) 47 | - [Update](#update) 48 | - [Security](#security) 49 | - [Backup](#backup) 50 | 51 | 52 | 53 | # Files structure 54 | 55 | ```bash 56 | . 57 | |-- docker-compose.yml 58 | |-- etc-dnsmasq.d/ 59 | |-- etc-pihole/ 60 | |-- unbound/ 61 | `-- wireguard/ 62 | ``` 63 | 64 | * `docker-compose.yml` - a docker-compose file, use to configure your application’s services 65 | * `etc-dnsmasq.d/` - a directory used to store dnsmasq configs 66 | * `etc-pihole/` - a directory used to store your Pi-hole configs 67 | * `wireguard/` - a directory used to store wireguard data, including client ready-to-use configuration files 68 | * `unbound/` - a directory used to store unbound data 69 | 70 | Please make sure that all the files and directories are present. 71 | 72 | # Information 73 | 74 | ## docker-compose 75 | 76 | Links to the following [docker-compose.yml](docker-compose.yml) and the corresponding [.env](.env). 77 | 78 | * docker-compose.yml 79 | ```yaml 80 | version: "3" 81 | 82 | services: 83 | unbound: 84 | image: mvance/unbound:latest 85 | container_name: unbound 86 | restart: unless-stopped 87 | hostname: unbound 88 | volumes: 89 | - ./unbound:/opt/unbound/etc/unbound/ 90 | networks: 91 | private_network: 92 | ipv4_address: 10.2.0.200 93 | labels: 94 | # Watchtower Update 95 | - "com.centurylinklabs.watchtower.enable=true" 96 | 97 | 98 | wireguard: 99 | depends_on: [unbound, pihole] 100 | image: linuxserver/wireguard 101 | container_name: wireguard 102 | restart: unless-stopped 103 | cap_add: 104 | - NET_ADMIN 105 | - SYS_MODULE 106 | environment: 107 | - PUID=${PUID} 108 | - PGID=${PGID} 109 | - TZ=${TZ} 110 | - SERVERPORT=51820 111 | - SERVERURL=${SERVERURL} #optional 112 | - PEERS=${PEERS} # How many peers to generate for you (clients) 113 | - PEERDNS=10.2.0.100 # Set it to point to pihole 114 | - INTERNAL_SUBNET=10.6.0.0 115 | volumes: 116 | - ./wireguard:/config 117 | - /lib/modules:/lib/modules 118 | ports: 119 | - "51820:51820/udp" 120 | dns: 121 | - 10.2.0.100 # Points to pihole 122 | - 10.2.0.200 # Points to unbound 123 | sysctls: 124 | - net.ipv4.conf.all.src_valid_mark=1 125 | networks: 126 | private_network: 127 | ipv4_address: 10.2.0.3 128 | labels: 129 | # Watchtower Update 130 | - "com.centurylinklabs.watchtower.enable=true" 131 | 132 | pihole: 133 | depends_on: [unbound] 134 | container_name: pihole 135 | image: pihole/pihole:latest 136 | restart: unless-stopped 137 | hostname: pihole 138 | dns: 139 | - 127.0.0.1 140 | - 10.2.0.200 # Points to unbound 141 | environment: 142 | TZ: "Europe/Paris" 143 | WEBPASSWORD: "" # Blank password - Can be whatever you want. 144 | ServerIP: 10.1.0.100 # Internal IP of pihole 145 | DNS1: 10.2.0.200 # Unbound IP 146 | DNS2: 10.2.0.200 # If we don't specify two, it will auto pick google. 147 | # Volumes store your data between container upgrades 148 | volumes: 149 | - "./etc-pihole/:/etc/pihole/" 150 | - "./etc-dnsmasq.d/:/etc/dnsmasq.d/" 151 | # Recommended but not required (DHCP needs NET_ADMIN) 152 | # https://github.com/pi-hole/docker-pi-hole#note-on-capabilities 153 | cap_add: 154 | - NET_ADMIN 155 | networks: 156 | private_network: 157 | ipv4_address: 10.2.0.100 158 | labels: 159 | # Watchtower Update 160 | - "com.centurylinklabs.watchtower.enable=true" 161 | 162 | networks: 163 | private_network: 164 | ipam: 165 | driver: default 166 | config: 167 | - subnet: 10.2.0.0/24 168 | ``` 169 | * .env 170 | ```ini 171 | SERVERURL=vpn.example.com 172 | 173 | # How many peers to generate for you (clients) 174 | PEERS=2 175 | 176 | # user PUID and group PGID - can be found by running id your-user 177 | PUID=1000 178 | PGID=1000 179 | ``` 180 | 181 | # Usage 182 | 183 | ## Requirements 184 | 185 | * A subdomain of your choice for your VPN, this example uses `vpn`. 186 | * You should be able to create a subdomain with your DNS provider, use a `A record` with the same IP address as your root domain. 187 | * Ports 51820 open, check your firewall. 188 | 189 | ## Configuration 190 | 191 | The linuxserver images are using the PUID and PGID, they allow the container to map the container's internal user to a user on the host machine, more information [here](https://docs.linuxserver.io/general/understanding-puid-and-pgid). 192 | 193 | To find yours, use `id user`. Replace the environment variables in `.env` with your own, then run : 194 | 195 | ```bash 196 | sudo docker-compose up -d 197 | ``` 198 | 199 | ### Wireguard 200 | 201 | * Getting the client configuration file 202 | 203 | You should be able to find the required configuration for your clients in the `wireguard` directory. Each client will have an associated folder called `peerX`. 204 | Inside this folder you can find a QR code for your smartphone as well as configuration file for your linux/windows. 205 | 206 | * Adding more clients 207 | 208 | If you want more clients, just change the value in the `.env` file and relaunch the service `sudo docker-compose up -d`. 209 | 210 | 211 | ### Pihole 212 | 213 | Once connected to the VPN you should be able to access the pihole admin interface at http://10.2.0.100/admin, for more information regarding pihole you can check the well written official pihole [documentation](https://docs.pi-hole.net/). 214 | 215 | # Update 216 | 217 | The images are automatically updated with [watchtower](../watchtower) thanks to the following label : 218 | 219 | ```yaml 220 | # Watchtower Update 221 | - "com.centurylinklabs.watchtower.enable=true" 222 | ``` 223 | 224 | # Security 225 | 226 | A VPN is often a good solution to always have a dedicated IP. If you want to secure your others services, you can limit their access only when you are connected to your VPN. An easy way to do that is to add the private IP address range used by docker (172.16.0.0/12), your internal IP through the VPN will be one of this range, to the traefik [whitelist](traefik/rules/whitelist.yml). 227 | 228 | Keep in mind that only the containers that have the following label attached will be prone to this IP restriction. 229 | 230 | ```yaml 231 | # Ip filtering 232 | - "traefik.http.routers.service-router-name.middlewares=whitelist@file" 233 | ``` 234 | 235 | # Backup 236 | 237 | Docker volumes are globally backed up using [borg-backup](../borg-backup). 238 | -------------------------------------------------------------------------------- /wireguard-pihole-unbound/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | unbound: 5 | image: mvance/unbound:latest 6 | container_name: unbound 7 | restart: unless-stopped 8 | hostname: unbound 9 | volumes: 10 | - ./unbound:/opt/unbound/etc/unbound/ 11 | networks: 12 | private_network: 13 | ipv4_address: 10.2.0.200 14 | labels: 15 | # Watchtower Update 16 | - "com.centurylinklabs.watchtower.enable=true" 17 | 18 | 19 | wireguard: 20 | depends_on: [unbound, pihole] 21 | image: linuxserver/wireguard 22 | container_name: wireguard 23 | restart: unless-stopped 24 | cap_add: 25 | - NET_ADMIN 26 | - SYS_MODULE 27 | environment: 28 | - PUID=${PUID} 29 | - PGID=${PGID} 30 | - TZ=${TZ} 31 | - SERVERPORT=51820 32 | - SERVERURL=${SERVERURL} #optional 33 | - PEERS=${PEERS} # How many peers to generate for you (clients) 34 | - PEERDNS=10.2.0.100 # Set it to point to pihole 35 | - INTERNAL_SUBNET=10.6.0.0 36 | volumes: 37 | - ./wireguard:/config 38 | - /lib/modules:/lib/modules 39 | ports: 40 | - "51820:51820/udp" 41 | dns: 42 | - 10.2.0.100 # Points to pihole 43 | - 10.2.0.200 # Points to unbound 44 | sysctls: 45 | - net.ipv4.conf.all.src_valid_mark=1 46 | networks: 47 | private_network: 48 | ipv4_address: 10.2.0.3 49 | labels: 50 | # Watchtower Update 51 | - "com.centurylinklabs.watchtower.enable=true" 52 | 53 | pihole: 54 | depends_on: [unbound] 55 | container_name: pihole 56 | image: pihole/pihole:latest 57 | restart: unless-stopped 58 | hostname: pihole 59 | dns: 60 | - 127.0.0.1 61 | - 10.2.0.200 # Points to unbound 62 | environment: 63 | TZ: "Europe/Paris" 64 | WEBPASSWORD: "" # Blank password - Can be whatever you want. 65 | ServerIP: 10.1.0.100 # Internal IP of pihole 66 | DNS1: 10.2.0.200 # Unbound IP 67 | DNS2: 10.2.0.200 # If we don't specify two, it will auto pick google. 68 | # Volumes store your data between container upgrades 69 | volumes: 70 | - "./etc-pihole/:/etc/pihole/" 71 | - "./etc-dnsmasq.d/:/etc/dnsmasq.d/" 72 | # Recommended but not required (DHCP needs NET_ADMIN) 73 | # https://github.com/pi-hole/docker-pi-hole#note-on-capabilities 74 | cap_add: 75 | - NET_ADMIN 76 | networks: 77 | private_network: 78 | ipv4_address: 10.2.0.100 79 | labels: 80 | # Watchtower Update 81 | - "com.centurylinklabs.watchtower.enable=true" 82 | 83 | networks: 84 | private_network: 85 | ipam: 86 | driver: default 87 | config: 88 | - subnet: 10.2.0.0/24 -------------------------------------------------------------------------------- /wireguard-pihole-unbound/unbound/unbound.conf: -------------------------------------------------------------------------------- 1 | server: 2 | ########################################################################### 3 | # BASIC SETTINGS 4 | ########################################################################### 5 | # Time to live maximum for RRsets and messages in the cache. If the maximum 6 | # kicks in, responses to clients still get decrementing TTLs based on the 7 | # original (larger) values. When the internal TTL expires, the cache item 8 | # has expired. Can be set lower to force the resolver to query for data 9 | # often, and not trust (very large) TTL values. 10 | cache-max-ttl: 86400 11 | 12 | # Time to live minimum for RRsets and messages in the cache. If the minimum 13 | # kicks in, the data is cached for longer than the domain owner intended, 14 | # and thus less queries are made to look up the data. Zero makes sure the 15 | # data in the cache is as the domain owner intended, higher values, 16 | # especially more than an hour or so, can lead to trouble as the data in 17 | # the cache does not match up with the actual data any more. 18 | cache-min-ttl: 60 19 | 20 | # Set the working directory for the program. 21 | directory: "/opt/unbound/etc/unbound" 22 | 23 | # RFC 6891. Number of bytes size to advertise as the EDNS reassembly buffer 24 | # size. This is the value put into datagrams over UDP towards peers. 25 | # 4096 is RFC recommended. 1472 has a reasonable chance to fit within a 26 | # single Ethernet frame, thus lessing the chance of fragmentation 27 | # reassembly problems (usually seen as timeouts). Setting to 512 bypasses 28 | # even the most stringent path MTU problems, but is not recommended since 29 | # the amount of TCP fallback generated is excessive. 30 | edns-buffer-size: 1472 31 | 32 | # Listen to for queries from clients and answer from this network interface 33 | # and port. 34 | interface: 0.0.0.0@53 35 | 36 | # Rotates RRSet order in response (the pseudo-random number is taken from 37 | # the query ID, for speed and thread safety). 38 | rrset-roundrobin: yes 39 | 40 | # Drop user privileges after binding the port. 41 | username: "_unbound" 42 | 43 | ########################################################################### 44 | # LOGGING 45 | ########################################################################### 46 | 47 | # Do not print log lines to inform about local zone actions 48 | log-local-actions: no 49 | 50 | # Do not print one line per query to the log 51 | log-queries: no 52 | 53 | # Do not print one line per reply to the log 54 | log-replies: no 55 | 56 | # Do not print log lines that say why queries return SERVFAIL to clients 57 | log-servfail: no 58 | 59 | # Further limit logging 60 | logfile: /dev/null 61 | 62 | # Only log errors 63 | verbosity: 1 64 | 65 | ########################################################################### 66 | # PRIVACY SETTINGS 67 | ########################################################################### 68 | 69 | # RFC 8198. Use the DNSSEC NSEC chain to synthesize NXDO-MAIN and other 70 | # denials, using information from previous NXDO-MAINs answers. In other 71 | # words, use cached NSEC records to generate negative answers within a 72 | # range and positive answers from wildcards. This increases performance, 73 | # decreases latency and resource utilization on both authoritative and 74 | # recursive servers, and increases privacy. Also, it may help increase 75 | # resilience to certain DoS attacks in some circumstances. 76 | aggressive-nsec: yes 77 | 78 | # Extra delay for timeouted UDP ports before they are closed, in msec. 79 | # This prevents very delayed answer packets from the upstream (recursive) 80 | # servers from bouncing against closed ports and setting off all sort of 81 | # close-port counters, with eg. 1500 msec. When timeouts happen you need 82 | # extra sockets, it checks the ID and remote IP of packets, and unwanted 83 | # packets are added to the unwanted packet counter. 84 | delay-close: 10000 85 | 86 | # Prevent the unbound server from forking into the background as a daemon 87 | do-daemonize: no 88 | 89 | # Add localhost to the do-not-query-address list. 90 | do-not-query-localhost: no 91 | 92 | # Number of bytes size of the aggressive negative cache. 93 | neg-cache-size: 4M 94 | 95 | # Send minimum amount of information to upstream servers to enhance 96 | # privacy (best privacy). 97 | qname-minimisation: yes 98 | 99 | ########################################################################### 100 | # SECURITY SETTINGS 101 | ########################################################################### 102 | # Only give access to recursion clients from LAN IPs 103 | access-control: 127.0.0.1/32 allow 104 | access-control: 192.168.0.0/16 allow 105 | access-control: 172.16.0.0/12 allow 106 | access-control: 10.0.0.0/8 allow 107 | # access-control: fc00::/7 allow 108 | # access-control: ::1/128 allow 109 | 110 | # File with trust anchor for one zone, which is tracked with RFC5011 111 | # probes. 112 | auto-trust-anchor-file: "var/root.key" 113 | 114 | # Enable chroot (i.e, change apparent root directory for the current 115 | # running process and its children) 116 | chroot: "/opt/unbound/etc/unbound" 117 | 118 | # Deny queries of type ANY with an empty response. 119 | #deny-any: yes 120 | 121 | # Harden against algorithm downgrade when multiple algorithms are 122 | # advertised in the DS record. 123 | harden-algo-downgrade: yes 124 | 125 | # RFC 8020. returns nxdomain to queries for a name below another name that 126 | # is already known to be nxdomain. 127 | harden-below-nxdomain: yes 128 | 129 | # Require DNSSEC data for trust-anchored zones, if such data is absent, the 130 | # zone becomes bogus. If turned off you run the risk of a downgrade attack 131 | # that disables security for a zone. 132 | harden-dnssec-stripped: yes 133 | 134 | # Only trust glue if it is within the servers authority. 135 | harden-glue: yes 136 | 137 | # Ignore very large queries. 138 | harden-large-queries: yes 139 | 140 | # Perform additional queries for infrastructure data to harden the referral 141 | # path. Validates the replies if trust anchors are configured and the zones 142 | # are signed. This enforces DNSSEC validation on nameserver NS sets and the 143 | # nameserver addresses that are encountered on the referral path to the 144 | # answer. Experimental option. 145 | harden-referral-path: no 146 | 147 | # Ignore very small EDNS buffer sizes from queries. 148 | harden-short-bufsize: yes 149 | 150 | # Refuse id.server and hostname.bind queries 151 | hide-identity: yes 152 | 153 | # Refuse version.server and version.bind queries 154 | hide-version: yes 155 | 156 | # Report this identity rather than the hostname of the server. 157 | identity: "DNS" 158 | 159 | # These private network addresses are not allowed to be returned for public 160 | # internet names. Any occurrence of such addresses are removed from DNS 161 | # answers. Additionally, the DNSSEC validator may mark the answers bogus. 162 | # This protects against DNS Rebinding 163 | private-address: 10.0.0.0/8 164 | private-address: 172.16.0.0/12 165 | private-address: 192.168.0.0/16 166 | private-address: 169.254.0.0/16 167 | private-address: fd00::/8 168 | private-address: fe80::/10 169 | private-address: ::ffff:0:0/96 170 | 171 | # Enable ratelimiting of queries (per second) sent to nameserver for 172 | # performing recursion. More queries are turned away with an error 173 | # (servfail). This stops recursive floods (e.g., random query names), but 174 | # not spoofed reflection floods. Cached responses are not rate limited by 175 | # this setting. Experimental option. 176 | #ratelimit: 1000 177 | 178 | # Use this certificate bundle for authenticating connections made to 179 | # outside peers (e.g., auth-zone urls, DNS over TLS connections). 180 | tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt 181 | 182 | # Set the total number of unwanted replies to eep track of in every thread. 183 | # When it reaches the threshold, a defensive action of clearing the rrset 184 | # and message caches is taken, hopefully flushing away any poison. 185 | # Unbound suggests a value of 10 million. 186 | unwanted-reply-threshold: 10000000 187 | 188 | # Use 0x20-encoded random bits in the query to foil spoof attempts. This 189 | # perturbs the lowercase and uppercase of query names sent to authority 190 | # servers and checks if the reply still has the correct casing. 191 | # This feature is an experimental implementation of draft dns-0x20. 192 | # Experimental option. 193 | #use-caps-for-id: yes 194 | 195 | # Help protect users that rely on this validator for authentication from 196 | # potentially bad data in the additional section. Instruct the validator to 197 | # remove data from the additional section of secure messages that are not 198 | # signed properly. Messages that are insecure, bogus, indeterminate or 199 | # unchecked are not affected. 200 | val-clean-additional: yes 201 | 202 | ########################################################################### 203 | # PERFORMANCE SETTINGS 204 | ########################################################################### 205 | # https://nlnetlabs.nl/documentation/unbound/howto-optimise/ 206 | # https://nlnetlabs.nl/news/2019/Feb/05/unbound-1.9.0-released/ 207 | 208 | # Number of slabs in the infrastructure cache. Slabs reduce lock contention 209 | # by threads. Must be set to a power of 2. 210 | # infra-cache-slabs: 4 211 | 212 | # Number of incoming TCP buffers to allocate per thread. Default 213 | # is 10. If set to 0, or if do-tcp is "no", no TCP queries from 214 | # clients are accepted. For larger installations increasing this 215 | # value is a good idea. 216 | # incoming-num-tcp: 10 217 | 218 | # Number of slabs in the key cache. Slabs reduce lock contention by 219 | # threads. Must be set to a power of 2. Setting (close) to the number 220 | # of cpus is a reasonable guess. 221 | # key-cache-slabs: 4 222 | 223 | # Number of bytes size of the message cache. 224 | # Unbound recommendation is to Use roughly twice as much rrset cache memory 225 | # as you use msg cache memory. 226 | msg-cache-size: 260991658 227 | 228 | # Number of slabs in the message cache. Slabs reduce lock contention by 229 | # threads. Must be set to a power of 2. Setting (close) to the number of 230 | # cpus is a reasonable guess. 231 | #msg-cache-slabs: 4 232 | 233 | # The number of queries that every thread will service simultaneously. If 234 | # more queries arrive that need servicing, and no queries can be jostled 235 | # out (see jostle-timeout), then the queries are dropped. 236 | # This is best set at half the number of the outgoing-range. 237 | # This Unbound instance was compiled with libevent so it can efficiently 238 | # use more than 1024 file descriptors. 239 | num-queries-per-thread: 4096 240 | 241 | # The number of threads to create to serve clients. 242 | # This is set dynamically at run time to effectively use available CPUs 243 | # resources 244 | #num-threads: 3 245 | 246 | # Number of ports to open. This number of file descriptors can be opened 247 | # per thread. 248 | # This Unbound instance was compiled with libevent so it can efficiently 249 | # use more than 1024 file descriptors. 250 | outgoing-range: 8192 251 | 252 | # Number of bytes size of the RRset cache. 253 | # Use roughly twice as much rrset cache memory as msg cache memory 254 | rrset-cache-size: 260991658 255 | 256 | # Number of slabs in the RRset cache. Slabs reduce lock contention by 257 | # threads. Must be set to a power of 2. 258 | #rrset-cache-slabs: 4 259 | 260 | # Do no insert authority/additional sections into response messages when 261 | # those sections are not required. This reduces response size 262 | # significantly, and may avoid TCP fallback for some responses. This may 263 | # cause a slight speedup. 264 | minimal-responses: yes 265 | 266 | # # Fetch the DNSKEYs earlier in the validation process, when a DS record 267 | # is encountered. This lowers the latency of requests at the expense of 268 | # little more CPU usage. 269 | prefetch: yes 270 | 271 | # Fetch the DNSKEYs earlier in the validation process, when a DS record is 272 | # encountered. This lowers the latency of requests at the expense of little 273 | # more CPU usage. 274 | prefetch-key: yes 275 | 276 | # Have unbound attempt to serve old responses from cache with a TTL of 0 in 277 | # the response without waiting for the actual resolution to finish. The 278 | # actual resolution answer ends up in the cache later on. 279 | serve-expired: yes 280 | 281 | # Open dedicated listening sockets for incoming queries for each thread and 282 | # try to set the SO_REUSEPORT socket option on each socket. May distribute 283 | # incoming queries to threads more evenly. 284 | so-reuseport: yes 285 | 286 | # Ensure kernel buffer is large enough to not lose messages in traffic spikes 287 | so-rcvbuf: 1m 288 | 289 | ########################################################################### 290 | # LOCAL ZONE 291 | ########################################################################### 292 | 293 | # # Include file for local-data and local-data-ptr 294 | # include: /opt/unbound/etc/unbound/a-records.conf 295 | # include: /opt/unbound/etc/unbound/srv-records.conf 296 | 297 | # ########################################################################### 298 | # # FORWARD ZONE 299 | # ########################################################################### 300 | 301 | # include: /opt/unbound/etc/unbound/forward-records.conf 302 | 303 | # OPTIONAL: 304 | # Forward Secure DNS to upstread provider Cloudflare DNS 305 | 306 | # forward-zone: 307 | # name: "." 308 | # forward-addr: 1.1.1.1@853#cloudflare-dns.com 309 | # forward-addr: 1.0.0.1@853#cloudflare-dns.com 310 | # forward-addr: 2606:4700:4700::1111@853#cloudflare-dns.com 311 | # forward-addr: 2606:4700:4700::1001@853#cloudflare-dns.com 312 | # forward-tls-upstream: yes 313 | 314 | remote-control: 315 | control-enable: no -------------------------------------------------------------------------------- /wordpress/.env: -------------------------------------------------------------------------------- 1 | TRAEFIK_WORDPRESS=wordpress.example.com 2 | DB_ROOT_PASSWD=xxxxxxxxxxxxxxx 3 | DB_PASSWD=xxxxxxxxxxxxxxx -------------------------------------------------------------------------------- /wordpress/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 |

4 | wordpress 5 |

6 | 7 | WordPress is a free and open source blogging tool and a content management system (CMS) based on PHP and MySQL, which runs on a web hosting service. 8 | 9 | * [Github](https://github.com/WordPress/WordPress) 10 | * [Documentation](https://codex.wordpress.org/) 11 | * [Docker Image](https://hub.docker.com/_/wordpress) 12 | 13 | # Table of Contents 14 | 15 | 16 | 17 | - [About](#about) 18 | - [Table of Contents](#table-of-contents) 19 | - [Files structure](#files-structure) 20 | - [Information](#information) 21 | - [docker-compose](#docker-compose) 22 | - [Usage](#usage) 23 | - [Requirements](#requirements) 24 | - [Configuration](#configuration) 25 | - [Update](#update) 26 | - [Backup](#backup) 27 | 28 | 29 | 30 | # Files structure 31 | 32 | ```bash 33 | . 34 | |-- .env 35 | |-- docker-compose.yml 36 | |-- wordpress-mysql/ 37 | `-- data/ 38 | ``` 39 | 40 | - `.env` - a file containing all the environment variables used in the docker-compose.yml 41 | - `docker-compose.yml` - a docker-compose file, use to configure your application’s services 42 | - `wordpress-mysql/` - a directory used to store the mysql data 43 | - `data/` - a directory used to store wordpress's data 44 | 45 | Please make sure that all the files and directories are present. 46 | 47 | # Information 48 | 49 | ## docker-compose 50 | Links to the following [docker-compose.yml](docker-compose.yml) and the corresponding [.env](.env). 51 | 52 | * docker-compose.yml 53 | ```yaml 54 | version: '3' 55 | 56 | services: 57 | db: 58 | image: mariadb 59 | container_name: wordpress-mysql 60 | restart: unless-stopped 61 | command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW 62 | volumes: 63 | - ./wordpress-mysql/db:/var/lib/mysql 64 | environment: 65 | - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWD} # Requested, set the root's password of MySQL service. 66 | - MYSQL_PASSWORD=${DB_PASSWD} 67 | - MYSQL_DATABASE=wordpress 68 | - MYSQL_USER=wordpress 69 | - MYSQL_LOG_CONSOLE=true 70 | networks: 71 | - wordpress-net 72 | labels: 73 | # Watchtower Update 74 | - "com.centurylinklabs.watchtower.enable=true" 75 | 76 | wordpress: 77 | image: wordpress:latest 78 | container_name: wordpress 79 | restart: unless-stopped 80 | volumes: 81 | - ./data:/var/www/html 82 | networks: 83 | - proxy 84 | - wordpress-net 85 | depends_on: 86 | - db 87 | labels: 88 | - "traefik.enable=true" 89 | - "traefik.http.routers.wordpress.rule=Host(`${TRAEFIK_WORDPRESS}`)" 90 | - "traefik.http.routers.wordpress.entrypoints=https" 91 | - "traefik.http.routers.wordpress.tls=true" 92 | - "traefik.http.routers.wordpress.tls.certresolver=mydnschallenge" 93 | # Watchtower Update 94 | - "com.centurylinklabs.watchtower.enable=true" 95 | 96 | networks: 97 | wordpress-net: 98 | proxy: 99 | external: true 100 | ``` 101 | * .env 102 | ```ini 103 | TRAEFIK_WORDPRESS=wordpress.example.com 104 | DB_ROOT_PASSWD=xxxxxxxxxxxxxxx 105 | DB_PASSWD=xxxxxxxxxxxxxxx 106 | ``` 107 | 108 | 109 | 110 | # Usage 111 | 112 | ## Requirements 113 | - [Traefik up and running](../traefik). 114 | - A subdomain of your choice, this example uses `wordpress`. 115 | - You should be able to create a subdomain with your DNS provider, use a `A record` with the same IP address as your root domain. 116 | 117 | ## Configuration 118 | 119 | Replace the environment variables in `.env` with your own. 120 | 121 | Then replace the following variables in `data/wp-config.php`. 122 | 123 | * DB_PASSWORD is equivalent to DB_PASSWD in `.env` 124 | ``` 125 | define( 'DB_PASSWORD', 'xxxxxxxxxxxxxxx' ); 126 | ``` 127 | 128 | * Change the following unique keys and salt, you can use this [wordpress salt generator](https://api.wordpress.org/secret-key/1.1/salt/) and copy past it 129 | ``` 130 | define( 'AUTH_KEY', 'change-me' ); 131 | define( 'SECURE_AUTH_KEY', 'change-me' ); 132 | define( 'LOGGED_IN_KEY', 'change-me' ); 133 | define( 'NONCE_KEY', 'change-me' ); 134 | define( 'AUTH_SALT', 'change-me' ); 135 | define( 'SECURE_AUTH_SALT', 'change-me' ); 136 | define( 'LOGGED_IN_SALT', 'change-me' ); 137 | define( 'NONCE_SALT', 'change-me' ); 138 | ``` 139 | 140 | You can now run : 141 | 142 | ```bash 143 | sudo docker-compose up -d 144 | ``` 145 | 146 | You should now be able to access the wordpress initialisation page. 147 | 148 | # Update 149 | 150 | The image is automatically updated with [watchtower](../watchtower) thanks to the following label : 151 | 152 | ```yaml 153 | # Watchtower Update 154 | - "com.centurylinklabs.watchtower.enable=true" 155 | ``` 156 | ACCESS_DENIED\ 157 | # Backup 158 | 159 | Docker volumes are globally backed up using [borg-backup](../borg-backup). -------------------------------------------------------------------------------- /wordpress/data/wp-config.php: -------------------------------------------------------------------------------- 1 |