https://github.com/zorgch/zorg-docker
Docker setup to run the zorg.ch Website and its related services in an isolated, server-independent environment.
https://github.com/zorgch/zorg-docker
docker docker-compose server zorg
Last synced: 5 months ago
JSON representation
Docker setup to run the zorg.ch Website and its related services in an isolated, server-independent environment.
- Host: GitHub
- URL: https://github.com/zorgch/zorg-docker
- Owner: zorgch
- License: gpl-3.0
- Created: 2022-11-03T19:17:13.000Z (over 3 years ago)
- Default Branch: live
- Last Pushed: 2025-12-26T18:33:51.000Z (6 months ago)
- Last Synced: 2025-12-28T07:57:25.443Z (6 months ago)
- Topics: docker, docker-compose, server, zorg
- Language: Shell
- Homepage: https://zorg.ch
- Size: 559 KB
- Stars: 1
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
zorg on Docker
===
> *Portable, Server independent, Docker-based code to get the zorg Websites and Services up, running, and hosted.*
---
**Table of Contents**
[π Pre-requisites](#-pre-requisites)
- [git installation](#git-installation)
- [Docker installation](#docker-installation)
- [π DNS-records and Hosts](#-dns-records-and-hosts)
- [π Folder structure setup](#-folder-structure-setup)
- [πΎ Docker images](#-docker-images)
- [𧬠Docker networking](#-docker-networks)
[π Getting started](#-getting-started)
- [Initial setup (one time only)](#initial-setup-one-time-only)
- [β© Update the cloned `zorg-docker` git repository](#-update-the-local-cloned-zorg-docker-git-repository)
[π¦ Docker services](#-docker-services)
- [Manage general services](#manage-general-services)
- [Single Β«KeePass SFTPΒ» service](#run-the-keepass-sftp-service-separately)
- [Single Β«Quake 3 Arena ServerΒ»](#run-the-quake-3-arena-server-separately)
- [Single Β«phpDocumentorΒ» service](#run-the-phpdocumentor-service-separately)
- [π·οΈ Docker services -> profiles mapping](#%EF%B8%8F-docker-services---profiles-mapping)
- [π©Ί Resource usage & services health](#docker-resource-usage---services-health)
- [π Update all Docker images](#-update-all-docker-images)
[π¨βπ« Explanations](#%E2%80%8D-explanations)
- [π§ͺ Debugging Docker Services](#-debugging-docker-services)
- [π₯ Firewall ports configuration](#-firewall-ports-configuration)
- [π The `/zorg-docker/resources`-directory & files](#-the-zorg-dockerresources-directory--files)
- [π logrotate handling](#-logrotate-must-be-done-on-the-host)
- [πΏ Import/export SQL-dumps with MariaDB](#-importexport-sql-dumps-with-mariadb)
---
## π Pre-requisites
### git installation
Install **git** [for your OS](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).
### Docker installation
Following the [official installation instructions](https://docs.docker.com/engine/install/) for **Docker**.
> [!TIP]
> On Ubuntu it's advised *against installing via snap*, as this may cause compatibility issues!
#### π DNS-records and Hosts
For all Hosts (subdomains) on the main Domain, the correspoinding DNS A-records with IP must be set up.
Example A-records
```bash
mail.domain.ch. 600 IN MX 178.nn.nn.nn
*.domain.ch. 600 IN A 178.nn.nn.nn
www.domain.ch. 600 IN A 178.nn.nn.nn
dockerstatus.domain.ch. 600 IN A 178.nn.nn.nn
```
##### π¨βπ» Working locally (development)? Add `hosts`!
On production a proper setup with pointing DNS for the root domain to the server's IP-address, this should not be necessary. But **locally** with a dummy domain, the domain & hostnames must be added to the `/etc/hosts`-file:
Example `hosts`-entries
(adjust as per your `.env` settings)
```bash
127.0.0.1 zdocker.dev
127.0.0.1 status.zdocker.dev
127.0.0.1 www.zdocker.dev
127.0.0.1 db.zdocker.dev
127.0.0.1 ftp.zdocker.dev
127.0.0.1 irc.zdocker.dev
127.0.0.1 pw.zdocker.dev
127.0.0.1 smtp.zdocker.dev
127.0.0.1 quake.zdocker.dev
```
## π Getting started
In general make sure to work from the project root directory:
`cd /srv//`
### π Folder structure setup
Creat the a folder structure on your host machine that reflects the following:
> [!IMPORTANT]
> This is just a proposal, folder structures & names can be different!
```
βββ www <-- (Your project root directory)
β
βββ zorg-docker/ <-- Pulled Git repository (repo)
β
βββ .env <-- Copy & adjust ".env.example" from repo
βββ docker-compose.yml <-- Symbolic-linked ./zorg-docker/docker-compose.yml
βββ docker-update.sh <-- Symbolic-linked ./zorg-docker/docker-update.sh
β
βββ reverseproxy/ <-- (Optional) To further customize OWASP WAF rules or IP-Whitelist. Ref in .env
βΒ Β βββ owasp-coraza-waf.yaml
|
βββ website/ <-- zorg Website configs & data
β βββ .env <-- .env file for Website
β βββ apache.conf <-- Copy & adjust "website/apache/example.conf" from repo
β β βββ data/ <-- Website /data/ folder & files
β βΒ Β βββ files/ (user generated content for zorg website)
β βΒ Β βββ gallery/
β βΒ Β βββ tauschboerse/
β β βββ ...
β βββ cronjobs/
β βΒ Β βββ cronjobs.crontab <-- Copy & adjust "website/php/example.crontab" from repo
β βββ sendmail/
β Β Β βββ msmtprc <-- Copy & adjust "website/sendmail/example-msmtprc" from repo
β
βββ mailserver/ <-- (Optional) To further customize Postfix SMTP. Reference in .env
βΒ Β βββ postfix-main.cf
|
βββ irc/
βΒ Β βββ anope-configs/ <-- Copy & adjust "irc/anope-example-sensitive-includes" from repo
β βΒ Β βββ sensitive-channels.conf
β βΒ Β βββ sensitive-mail.conf
β βΒ Β βββ sensitive-networkinfo.conf
β βΒ Β βββ sensitive-nicknames.conf
β βΒ Β βββ sensitive-operators.conf
β βΒ Β βββ sensitive-serverinfo.conf
β βΒ Β βββ sensitive-uplink.conf
β βΒ Β βββ services.motd
βΒ Β βββ ircd-configs/ <-- Copy & adjust "irc/unrealircd-example-sensitive-includes" from repo
β βββ ircd.motd
β βββ sensitive-admin.conf
β βββ sensitive-history.conf
β βββ sensitive-me.conf
β βββ sensitive-network.conf
β βββ sensitive-operators.conf
β βββ sensitive-server.conf
β βββ sensitive-servicelink.conf
β βββ ssl/
β
βββ code-docu/
βΒ Β βββ code/ <-- (Optional) Git clone of github.com/zorgch/zorg-code.git. Reference in .env
βΒ Β βββ docu/ <-- (Optional) Reference in .env
βΒ Β βββ phpdoc.xml <-- (Optional)
β
βββ keepass/ <-- Reference in .env Only AFTER sftp started: put kdbx file here.
β
βββ quake3-baseq3/ <-- Reference in .env
βΒ βββ q3config_server.cfg <-- Copy & adjust "quake3/example-server.cfg" from repo
βΒ Β βββ pak0.pk3 <-- From a local licensed Quake3 installation
βΒ Β βββ pak1-8.pk3 <-- Can be obtained at: https://ioquake3.org/extras/patch-data/
β
βββ logs/ <-- Reference in .env
βββ website/ <-- Sub-directories MUST also be created manually!
β βββ apache/
β βββ php/
β βββ sendmail/
β βββ website/
βββ reverseproxy-owasp/
βββ mariadb/
βββ mailserver-smtp/
βββ irc-server/ <-- β οΈ Requires: sudo chown -R 1000:1000
βββ sftp/
βββ quake3-server/
```
### πΎ Docker images
Here's an overview of the underlaying Docker images used for the Docker Services, in order to provide quick access to their documentation & configuration how-to's.
Click to show list
| Service | Docker image | Link |
| ------------------ | ------------------------- | ------------------ |
| `sslcerts` | `alpine/mkcert` | [GitHub](https://github.com/alpine-docker/multi-arch-docker-images/tree/master/mkcert) |
| `dashboard` | `portainer/portainer-ce` | [Docs](https://docs.portainer.io/start/install-ce/server/docker) |
| `reverseproxy`
+ `owasp-coraza-waf@file` | `traefik`
`coraza-http-wasm-traefik` | [Docs](https://doc.traefik.io/traefik/)
[GitHub](https://github.com/jcchavezs/coraza-http-wasm-traefik) |
| `website` | `php` | [Docker Hub](https://hub.docker.com/_/php) |
| `db` | `mariadb` | [Docs](https://mariadb.com/kb/en/mariadb-server-docker-official-image-environment-variables/) |
| `db-manager` | `adminer` | [Docs](https://hub.docker.com/_/adminer/#how-to-use-this-image) |
| `postfix-smtp` | `mailserver/docker-mailserver` | [Docs](https://docker-mailserver.github.io/docker-mailserver/) |
| `irc` | `c0dy/unrealircd-anope` | [Docker Hub](https://hub.docker.com/r/c0dy/unrealircd-anope) |
| `irc-quizbot` | `python:3.12-slim` | [GitHub](https://github.com/zorgch/irc-quizbot) |
| `irc-telegram-bridge` | `bhavin192/teleirc` | [Docker Hub](https://hub.docker.com/r/bhavin192/teleirc) |
| `stockticker` | `python:3.12-slim` | [GitHub](https://github.com/zorgch/zorg-docker/tree/dev/resources/python/stockticker) |
| `servicealerts` | `lorcas/docker-telegram-notifier` | [GitHub](https://github.com/luc-ass/docker-telegram-notifier) |
| `sftp` | `atmoz/sftp` | [Docker Hub](https://hub.docker.com/r/atmoz/sftp/) |
| `quake3` | `jberrenberg/quake3` | [GitHub](https://github.com/jberrenberg/docker-quake3/tree/master/quake3) |
| `phpdoc` | `phpdoc/phpdoc` | [Docs](https://docs.phpdoc.org/guide/guides/running-phpdocumentor.html#running-phpdocumentor) |
### 𧬠Docker Networks
In order to not block Ports for other networking services on the server / in other Docker stacks, this Docker stack has support for [HTTP, TCP (dedicated), and UDP shared networks](#add-external-docker-networks) (aka External Docker Networks).
These are optional, but highly recommended to use - in order to prevent future port conflicts. Here's a schematic overview of the networking capabilities added:
```mermaid
graph TD
%% Externe Netzwerke
subgraph External Networks
lb_http["loadbalance-http
[external/shared]"]
lb_tcp["loadbalance-tcp
[external/shared]"]
lb_udp["loadbalance-udp
[external/shared]"]
end
%% zorg Main
subgraph zorg Live
zorg[zorg services]
grid["the-grid
β loadbalance-http"]
superhighway["information-superhighway
β loadbalance-tcp"]
slipgate["slipgate-teleporter
β loadbalance-udp"]
zion["zion-mainframe
[internal only]"]
end
%% zorg Construct
subgraph zorg Construct
stack1[construct services]
stack1_http["β loadbalance-http"]
stack1_tcp["β loadbalance-tcp"]
stack1_udp["β loadbalance-udp"]
internalnet["custom-net
[internal only]"]
end
%% Weitere Stacks
subgraph other-stack-2
stack2[stack 2 services]
stack2_http["β loadbalance-http"]
stack2_internalnet["stack2_default
[internal only]"]
end
subgraph other-stack-3
stack3[stack 3 services]
stack3_tcp["β loadbalance-tcp"]
stack3_udp["β loadbalance-udp"]
end
%% Verbindungen zorg
zorg --> grid --> lb_http
zorg --> superhighway --> lb_tcp
zorg --> slipgate --> lb_udp
zorg --> zion
%% Verbindungen andere Stacks
stack1 --> stack1_http --> lb_http
stack1 --> stack1_tcp --> lb_tcp
stack1 --> stack1_udp --> lb_udp
stack1 --> internalnet
stack2 --> stack2_http --> lb_http
stack2 --> stack2_internalnet
stack3 --> stack3_tcp --> lb_tcp
stack3 --> stack3_udp --> lb_udp
```
### Initial setup (one time only)
#### Git clone the `zorg-docker` repository
```bash
git clone -b --depth 1 https://github.com/zorgch/zorg-docker.git ./zorg-docker
```
> [!NOTE]
> See below section for how to UPDATE the cloned git repository to get its latest changes.
##### Edit a copy of the `.env`-file
```bash
cp ./zorg-docker/.env.example ./.env
```
> [!IMPORTANT]
> Using your text editor of choice, adjust the `.env`-file to the setup of your host machine.
##### Create a symbolic link to `docker-compose.yml`
```bash
ln -s ./zorg-docker/docker-compose.yml ./docker-compose.yml
```
#### Add external Docker networks
These networks allow OTHER Docker Stacks and Services to connect to the same network.
```bash
docker network create loadbalance-http
docker network create loadbalance-tcp
docker network create loadbalance-udp
```
> [!NOTE]
> Why is this important?
> A: Access to Docker Services in the Stack from other Docker Stacks and Services.
> B: This is particularly important to use **1 central Reverse-Proxy** to route traffic to the services in the correct Stack.
> C: Conclusion of A & B means: *no Port blockings of common Ports* (e.g. `80` or `443`) by 1 single Docker Stack!
#### Validate the Docker services configurations
```bash
docker compose build
```
#### π TLS/SSL: generate self-signed certificates
Some services require self-signed certificates, this does not interfere with (also) using Let's Encrypt certificates!
Add these first using the `sslcerts` service:
```bash
docker compose --profile setup up
```
#### π§ Mailserver (SMTP) configuration
> [!NOTE]
> This requires the mailserver service to be running!
##### Add postfix accounts & email forwarding
> [!TIP]
> This is required when emails to a local user (alias) should be forwarded to an external email address corresponding to that alias.
```
docker exec -ti PROJECTNAME-mailserver setup email add info@DOMAINNAME
docker exec -ti PROJECTNAME-mailserver setup alias add
```
##### General mailserver setup help
The docker-mailserver setup is required for various configurations, including for example [DKIM](https://docker-mailserver.github.io/docker-mailserver/v11.0/config/best-practices/dkim/).
```
docker exec -ti PROJECTNAME-mailserver setup
docker exec -ti PROJECTNAME-mailserver setup config dkim help
```
### β© Update the local cloned `zorg-docker` git repository
cd into the directory containing the locally cloned git files, and run a git pull:
```bash
cd /srv///zorg-docker
git pull --rebase
```
> [!IMPORTANT]
> Check the updated Files and apply necessary changes to outdated manual copies of the same!
- Example:
```bash
Fast-forward
.env.example | 17 +++++--------
docker-compose.yml | 75 ++++++++++++++++++++++++++++++++++++-------------------
resources/irc/unrealircd/unrealircd.conf | 12 ++++-----
resources/mailserver/postfix-main.cf | 4 +--
resources/reverseproxy/middlewares-http.yaml | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
resources/reverseproxy/selfsigned-certs.yaml | 23 ++++++++---------
6 files changed, 207 insertions(+), 90 deletions(-)
```
## π¦ Docker services
### Manage general services
**PRODUCTION mode** β run in "detached mode" (background), *without* interative logging to the shell by adding the `-d` flag.
Start/stop all services *
```bash
docker compose --profile all up -d
```
* Applicable services: `servicealerts`, `dashboard`, `reverseproxy`, `website`, `db`, `postfix-smtp`, `irc`, `irc-quizbot`, `irc-telegram-bridge`, `stockticker`, `sftp`, `quake3`
Example: only the Webserver services
```bash
docker compose --profile webserver up -d
```
* Applicable services: `servicealerts`, `dashboard`, `reverseproxy`, `website`, `db`, `postfix-smtp`
Example 2: only the IRC services
```bash
docker compose --profile irc up -d
```
* Applicable services: `servicealerts`, `dashboard`, `irc`, `irc-quizbot`, `irc-telegram-bridge`
Example 2: only the Mailserver services
```bash
docker compose --profile mailserver up -d
```
* Applicable services: `servicealerts`, `dashboard`, `reverseproxy`, `postfix-smtp`
> [!CAUTION]
> Do not take an individual service *down* using `--profile`, target it specifically instead!
`docker compose down stockticker`
#### Run the KeePass SFTP-service (separately)
* As provisioning a KeePass KDBX via SFTP is not required for the general website hosting, the SFTP service (`keepass`) is separated from the overall services.
```bash
docker compose --profile keepass up -d
docker compose down sftp
```
#### Run the Quake 3 Arena Server (separately)
* Due to a potential high load on the server, the Β«Quake 3 ArenaΒ» Server (`quake3`) is separated from the general services.
```bash
docker compose up -d quake3
docker compose down quake3
```
#### Run the phpDocumentor service (separately)
* As the code generation is only run occassionally, the phpDoc service (`phpdoc`) is separated from the general services.
```bash
docker compose --profile docu up
# exits automatically
```
### π·οΈ Docker services -> profiles mapping
The `docker-compose.yml` file uses Docker Service-profiles to group services into logical groups.
* This allows to only start / stop a certain group of services at once.
* Yet individual docker services can still be targeted individually by referencing their service name.
Some single services have their own profile, in order to prevent them from starting/stopping when using `docker compose` without any `--profile`.
> [!TIP]
> Multiple profiles can be combined: `docker compose --profile webserver --profile irc up -d`
| Profile | Applicablae Docker Services | Example Usage |
| -------------- | ------------------------------------ | -------------------------------|
| `all` | All general services | `--profile all` |
| `setup` | `sslcerts` `postfix-smtp` | `--profile setup` |
| `status` | `servicealerts` `dashboard` `reverseproxy` | `--profile status` |
| `webserver` | `servicealerts` `dashboard` `reverseproxy` `website` `db` `db-manager` `postfix-smtp` | `--profile webserver` |
| `mailserver` | `servicealerts` `dashboard` `reverseproxy` `postfix-smtp` | `--profile mailserver` |
| `irc` | `servicealerts` `dashboard` `irc` `irc-quizbot` `irc-telegram-bridge` | `--profile irc` |
| `keepass` | `servicealerts` `dashboard` `sftp` | `--profile keepass` |
| `quake` | `servicealerts` `dashboard` `quake3` | `--profile quake` |
| `docu` | `phpdoc` | `--profile docu` |
| Single service | e.g. `stockticker` | `docker compose up -d stockticker` |
## π©Ί Docker resource usage & services health
### Quick resource analysis using the CLI
This is particularly helpful to fine-tune the CPU & memory limits for the Docker services, which can be adjusted in the `.env`-file.
```bash
docker stats
```
Example docker status output
```bash
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}"
NAME CPU % MEM USAGE / LIMIT MEM %
zorg-reverseproxy 0.00% 69.01MiB / 1GiB 6.74%
zorg-stockticker 0.03% 70.19MiB / 1GiB 6.85%
zorg-mariadb 0.01% 133.8MiB / 4GiB 3.27%
zorg-website 0.01% 8.855MiB / 4GiB 0.22%
zorg-dashboard 0.00% 27.06MiB / 1GiB 2.64%
zorg-mailserver 0.11% 39.41MiB / 256MiB 15.39%
```
### The Docker Status-Dashboard
The full-fledged Docker Management Dashboard (Portainer) can be accessed at:
* `https://dockerstatus.DOMAINNAME`
*Host can be adjusted in the `.env`*
## π Update all Docker images
cd into the directory containing the `docker-compose.yml` (symlink), and run this shell command:
> [!TIP]
> The images can be scoped to update only services within a specific [Docker services profile](#-docker-services---profiles-mapping)
```bash
cd /srv///
for image in $(docker compose --profile all config | awk '/image:/ { print $2 }'); do docker pull "$image"; done;
```
Alternatively, use the `docker-update.sh` script (can also be run via Host's cron):
```bash
cd /srv///
./docker-update.sh
```
> [!CAUTION]
> Updating Docker images will NOT renew running services - they have to be [rebuilt](#manage-general-services)!
## π¨βπ« Explanations
### π§ͺ Debugging Docker Services
For **DEBUGGING mode** β with an *interactive log output* to the active shell - omit the `-d` flag when starting services:
`docker compose --file ./website/docker-compose.yml up` <-- no `-d` flag
#### π₯ Firewall ports configuration
> [!TIP]
> Docker **circumvents** the Host machine's firewall β so usually NO need (or not possible) to configure the Host machine's firewall!
Ensure the Host machine's firewall is configured to expose & allow access through the required ports for different Docker Services:
Allow a port - or port range
A non-conclusive, depends on what `ports:` are set in the `.env` file.
> [!IMPORTANT]
> Do NOT expose the default Database port `3306` to the world-wide-web!
```bash
sudo ufw allow 80 # webserver/reverseproxy http
sudo ufw allow 443 # webserver/reverseproxy https
sudo ufw allow 9443/tcp # Docker dashboard (secure)
sudo ufw allow 6667/tcp # irc-Server
sudo ufw allow 6697/tcp # irc-Server (secure)
sudo ufw allow 2222/tcp # ftp-Server | NOTE: 22 reserved for ssh
sudo ufw allow 27960/udp # quake3-Server
```
Inspect all rules - i.e. allowed ports
```bash
% sudo ufw status
Status: active
To Action From
-- ------ ----
80 ALLOW Anywhere
443 ALLOW Anywhere
587 ALLOW Anywhere
6667/tcp ALLOW Anywhere
6697/tcp ALLOW Anywhere
2222/tcp ALLOW Anywhere
27960/udp ALLOW Anywhere
80 (v6) ALLOW Anywhere (v6)
443 (v6) ALLOW Anywhere (v6)
587 (v6) ALLOW Anywhere (v6)
6667/tcp (v6) ALLOW Anywhere (v6)
6697/tcp (v6) ALLOW Anywhere (v6)
2222/tcp (v6) ALLOW Anywhere (v6)
27960/udp (v6) ALLOW Anywhere (v6)
```
### π The `/zorg-docker/resources`-directory & files
Contains site specific resources that are actively mapped from the Host to some of the Docker Services. But it also contains some *example* files that can be used to configure the services.
Examples of example files
* `irc/anope-example-*` & `irc/unrealircd-example-*` --> MUST be adapted
* `website/apache/example.conf` --> use as `apache.conf`
* `website/php/example.crontab` --> use as `crontab`
* `website/sendmail/example-msmtprc` --> use as `msmtprc`
* `quake3/example-autoexec.cfg` --> use as `autoexec.cfg`
### π `logrotate` must be done on the Host
The Docker services are just writing logs to the mapped `/logs`-directory, but `logrotate` must be configured on the Host machine.
### πΏ Import/export SQL-dumps with MariaDB
A third-party SQL Manager (e.g. on macOS use [SequelAce](https://sequel-ace.com)) or CLI application is required to connect to the MariaDB service under the specified host and port.
#### Import an SQL dump
```bash
mysql -h -P 3306 -u MYSQL_USER -p MYSQL_DATABASE < /path/to/import-dump.sql
```
#### Export an SQL dump via CLI
```bash
mysqldump -h -P 3306 -u MYSQL_USER -p MYSQL_DATABASE > /path/to/save-dump.sql
```
---
## βοΈ License
> Copyright (C) 2024-2025 zorg Verein
>
> This program is free software: you can redistribute it and/or modify
> it under the terms of the GNU General Public License as published by
> the Free Software Foundation, either version 3 of the License, or
> (at your option) any later version.
>
> This program is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU General Public License for more details.
>
> You should have received a copy of the GNU General Public License
> along with this program. If not, see .
>
> This program comes with ABSOLUTELY NO WARRANTY; for details read the README.
> This is free software, and you are welcome to redistribute it
> under certain conditions; see the LICENSE.
---