# 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: ```bash # 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= # Gitea Runner GITEA_INSTANCE_URL=https://gitea.yourdomain.com GITEA_RUNNER_REGISTRATION_TOKEN= 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= MYSQL_TZ_BOOKSTACK=Europe/Rome # Bookstack App BOOKSTACK_APP_URL=https://bookstack.yourdomain.com BOOKSTACK_APP_KEY= # Vikunja POSTGRES_NAME_VIKUNJA=vikunja POSTGRES_USER_VIKUNJA=vikunja POSTGRES_PASSWORD_VIKUNJA= VIKUNJA_JWT_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: ```bash touch acme.json && chmod 600 acme.json ``` 2. Update the dashboard Basic Auth in `docker-compose.yaml`: ```bash # 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: ```bash 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 - **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`: ```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: ```bash 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 -n ``` --- ## Radicale CalDAV and CardDAV server for calendars and contacts sync. **URL:** `https://radicale.YOUR_DOMAIN` ### Setup 1. Create the users file: ```bash touch radicale/config/users ``` 2. Add users with bcrypt passwords: ```bash 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: ```bash cd opencloud-compose ``` 2. Create the environment file: ```bash cp .env.example .env ``` 3. Edit `.env` with required settings: ```bash INSECURE=true OC_DOCKER_IMAGE=opencloudeu/opencloud-rolling OC_DOMAIN=opencloud.yourdomain.com INITIAL_ADMIN_PASSWORD= LOG_PRETTY=true OC_CONFIG_DIR=./opencloud/config OC_DATA_DIR=./opencloud/data ``` 4. Create data directories: ```bash mkdir -p opencloud/{config,data} chown -R 1000:1000 opencloud ``` 5. For external proxy setup (using the main Traefik), set: ```bash COMPOSE_FILE=docker-compose.yml:external-proxy/opencloud.yml ``` 6. Start OpenCloud: ```bash docker compose up -d ``` ### References - [Behind External Proxy](https://github.com/opencloud-eu/opencloud-compose?tab=readme-ov-file#behind-external-proxy) - [GitHub Discussion](https://github.com/orgs/opencloud-eu/discussions/533) --- ## 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: ```bash docker compose --profile after up -d ``` --- ## Backup & Restore Automated cold backups using [docker-volume-backup](https://github.com/offen/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 ```bash ./backup.sh ``` ### Restore from Backup ```bash # 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`: ```bash 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 ```bash docker compose logs -f backup ``` --- ## Logs Access logs are stored in `./logs/traefik/` for Fail2Ban integration. View service logs: ```bash docker compose logs -f [service_name] ```