8.2 KiB
JMP Server Infrastructure
Docker Compose-based infrastructure deployment for self-hosted services.
Prerequisites
- Docker and Docker Compose installed
- A domain with DNS records pointing to your server
- Ports 80, 443, and 2222 (SSH for Gitea) open
Quick Start
- Create the
.envfile with required variables (see Environment Variables section) - Set up ACME storage:
touch acme.json && chmod 600 acme.json - Start services:
./start.shordocker compose up -d - Stop services:
./stop.shordocker compose down
Environment Variables
Create a .env file in the project root with the following variables:
# General
DOMAIN=yourdomain.com
PUID=1000
PGID=1000
# Gitea Database
POSTGRES_HOST_GITEA=gitea-db
POSTGRES_NAME_GITEA=gitea
POSTGRES_USER_GITEA=gitea
POSTGRES_PASSWORD_GITEA=<SECURE_PASSWORD>
# Gitea Runner
GITEA_INSTANCE_URL=https://gitea.yourdomain.com
GITEA_RUNNER_REGISTRATION_TOKEN=<TOKEN_FROM_GITEA>
GITEA_RUNNER_NAME=runner-1
GITEA_RUNNER_LABELS=ubuntu-latest:docker://node:16-bullseye
# Bookstack Database
MYSQL_HOST_BOOKSTACK=bookstack-db
MYSQL_PORT_BOOKSTACK=3306
MYSQL_NAME_BOOKSTACK=bookstack
MYSQL_USER_BOOKSTACK=bookstack
MYSQL_PASSWORD_BOOKSTACK=<SECURE_PASSWORD>
MYSQL_TZ_BOOKSTACK=Europe/Rome
# Bookstack App
BOOKSTACK_APP_URL=https://bookstack.yourdomain.com
BOOKSTACK_APP_KEY=<GENERATED_KEY>
# Vikunja
POSTGRES_NAME_VIKUNJA=vikunja
POSTGRES_USER_VIKUNJA=vikunja
POSTGRES_PASSWORD_VIKUNJA=<SECURE_PASSWORD>
VIKUNJA_JWT_SECRET=<RANDOM_SECRET>
Traefik
Reverse proxy and load balancer handling routing and HTTPS/TLS via Let's Encrypt.
URL: https://traefik.YOUR_DOMAIN
Setup
-
Create the ACME storage file:
touch acme.json && chmod 600 acme.json -
Update the dashboard Basic Auth in
docker-compose.yaml:# Generate a password hash echo $(htpasswd -nB admin) | sed -e s/\\$/\\$\\$/gReplace the
traefik.http.middlewares.auth.basicauth.userslabel value. -
Update the ACME email in
traefik.yml(line 54).
Gitea
Git repository hosting with PostgreSQL backend and CI/CD runner support.
URL: https://gitea.YOUR_DOMAIN
SSH: ssh://git@YOUR_DOMAIN:2222
Setup
- Set the database environment variables in
.env - Start the services
- Access the web interface to complete initial setup
- Create the first admin user
Admin
User registration is disabled by default. Use admin user to add new users from web UI
Gitea Runner
To enable CI/CD:
- In Gitea, go to Site Administration → Actions → Runners
- Click Create new Runner and copy the registration token
- Set
GITEA_RUNNER_REGISTRATION_TOKENin.env - Restart the runner container
Bookstack
Documentation wiki with MariaDB backend.
URL: https://bookstack.YOUR_DOMAIN
Setup
-
Generate an APP_KEY:
docker run -it --rm --entrypoint /bin/bash lscr.io/linuxserver/bookstack:latest appkey -
Add the key to
BOOKSTACK_APP_KEYin.env -
Set database environment variables in
.env -
Start the services
First Login
- Email: admin@admin.com
- Password: password
Change these immediately after first login.
Restore Backup From Different Url
Run a shell in bookstack container. For Example
docker exec -it bookstack-container sh
Then:
php artisan bookstack:update-url https://docs.jmpgames.it https://bookstack.jmpgames.it
php artisan migrate
Homepage
Dashboard for service discovery and monitoring.
URL: https://home.YOUR_DOMAIN (or http://localhost:3001)
Setup
A homepage/ directory is created after first boot containing configuration files.
To enable Docker container auto-detection, edit homepage/docker.yaml:
my-docker:
socket: /var/run/docker.sock
Services with homepage.* labels in docker-compose.yaml will appear automatically.
Vikunja
Task management and to-do lists with PostgreSQL backend.
URL: https://vikunja.YOUR_DOMAIN
Setup
- Set the database environment variables in
.env - Generate a random JWT secret:
openssl rand -base64 32 - Set
VIKUNJA_JWT_SECRETin.env - Start the services
- Register the first user (becomes admin)
Admin
Web UI user registration is disabled. To add new user:
# Example for Docker
docker exec vikunja /app/vikunja/vikunja user create -u "newuser" -e "user@example.com" -p "your_password"
To delete a user:
# Example for Docker
docker exec vikunja /app/vikunja/vikunja user list # Get user id
docker exec -it vikunja /app/vikunja/vikunja user delete <id> -n
Radicale
CalDAV and CardDAV server for calendars and contacts sync.
URL: https://radicale.YOUR_DOMAIN
Setup
-
Create the users file:
touch radicale/config/users -
Add users with bcrypt passwords:
htpasswd -Bc /dev/stdout USERNAME -
Append the output to
radicale/config/users:username:$2y$05$...
Client Configuration
Use the following URL for CalDAV/CardDAV clients:
https://radicale.YOUR_DOMAIN/USERNAME/
Supported clients: Thunderbird, DAVx5 (Android), iOS Calendar/Contacts, Evolution, GNOME Calendar.
OpenCloud
Nextcloud-based cloud storage platform.
URL: https://opencloud.YOUR_DOMAIN
Setup
-
Navigate to the OpenCloud compose directory:
cd opencloud-compose -
Create the environment file:
cp .env.example .env -
Edit
.envwith required settings:INSECURE=true OC_DOCKER_IMAGE=opencloudeu/opencloud-rolling OC_DOMAIN=opencloud.yourdomain.com INITIAL_ADMIN_PASSWORD=<SECURE_PASSWORD> LOG_PRETTY=true OC_CONFIG_DIR=./opencloud/config OC_DATA_DIR=./opencloud/data -
Create data directories:
mkdir -p opencloud/{config,data} chown -R 1000:1000 opencloud -
For external proxy setup (using the main Traefik), set:
COMPOSE_FILE=docker-compose.yml:external-proxy/opencloud.yml -
Start OpenCloud:
docker compose up -d
References
Website
Frontend web application (requires Gitea registry access).
URL: https://YOUR_DOMAIN
Setup
The website service is in the after profile and requires the container image to be built and pushed to the Gitea registry first.
Start with:
docker compose --profile after up -d
Backup & Restore
Automated cold backups using docker-volume-backup.
How It Works
- Daily backups at 3:00 AM (configurable in
backup.env) - Cold backups: Database containers are stopped during backup to ensure data consistency
- Retention: Backups older than 7 days are automatically deleted
- Storage: Local backups in
./backups/(optionally to S3/SSH/WebDAV)
Backed Up Data
| Service | Data |
|---|---|
| Gitea | Application data + PostgreSQL database |
| Bookstack | Application data + MariaDB database |
| Vikunja | Files + PostgreSQL database |
| Radicale | CalDAV/CardDAV data |
| Homepage | Dashboard configuration |
Manual Backup
./backup.sh
Restore from Backup
# List available backups
./restore.sh
# Restore specific backup
./restore.sh backup-2025-01-05T03-00-00.tar.gz
Configuration
Edit backup.env to configure:
- Schedule:
BACKUP_CRON_EXPRESSION(default: daily at 3 AM) - Retention:
BACKUP_RETENTION_DAYS(default: 7 days) - Encryption: Uncomment
GPG_PASSPHRASEfor encrypted backups - Remote storage: Configure S3, SSH, or WebDAV for offsite backups
- Notifications: Configure Discord, Slack, or email alerts
Remote Backup (S3 Example)
Add to backup.env:
AWS_S3_BUCKET_NAME=your-bucket
AWS_S3_PATH=jmp-server
AWS_ACCESS_KEY_ID=your-key
AWS_SECRET_ACCESS_KEY=your-secret
AWS_ENDPOINT=s3.amazonaws.com
View Backup Logs
docker compose logs -f backup
Logs
Access logs are stored in ./logs/traefik/ for Fail2Ban integration.
View service logs:
docker compose logs -f [service_name]