2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00
2026-01-10 23:34:39 +01:00

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

  1. Create the .env file with required variables (see Environment Variables section)
  2. Set up ACME storage: touch acme.json && chmod 600 acme.json
  3. Start services: ./start.sh or docker compose up -d
  4. Stop services: ./stop.sh or docker 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

  1. Create the ACME storage file:

    touch acme.json && chmod 600 acme.json
    
  2. Update the dashboard Basic Auth in docker-compose.yaml:

    # Generate a password hash
    echo $(htpasswd -nB admin) | sed -e s/\\$/\\$\\$/g
    

    Replace the traefik.http.middlewares.auth.basicauth.users label value.

  3. 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

  1. Set the database environment variables in .env
  2. Start the services
  3. Access the web interface to complete initial setup
  4. 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:

  1. In Gitea, go to Site Administration → Actions → Runners
  2. Click Create new Runner and copy the registration token
  3. Set GITEA_RUNNER_REGISTRATION_TOKEN in .env
  4. Restart the runner container

Bookstack

Documentation wiki with MariaDB backend.

URL: https://bookstack.YOUR_DOMAIN

Setup

  1. Generate an APP_KEY:

    docker run -it --rm --entrypoint /bin/bash lscr.io/linuxserver/bookstack:latest appkey
    
  2. Add the key to BOOKSTACK_APP_KEY in .env

  3. Set database environment variables in .env

  4. Start the services

First Login

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

  1. Set the database environment variables in .env
  2. Generate a random JWT secret:
    openssl rand -base64 32
    
  3. Set VIKUNJA_JWT_SECRET in .env
  4. Start the services
  5. 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

  1. Create the users file:

    touch radicale/config/users
    
  2. Add users with bcrypt passwords:

    htpasswd -Bc /dev/stdout USERNAME
    
  3. 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

  1. Navigate to the OpenCloud compose directory:

    cd opencloud-compose
    
  2. Create the environment file:

    cp .env.example .env
    
  3. Edit .env with 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
    
  4. Create data directories:

    mkdir -p opencloud/{config,data}
    chown -R 1000:1000 opencloud
    
  5. For external proxy setup (using the main Traefik), set:

    COMPOSE_FILE=docker-compose.yml:external-proxy/opencloud.yml
    
  6. 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_PASSPHRASE for 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]
Description
No description provided
Readme 262 KiB
Languages
Shell 100%