Skip to content

AlainPiallat/vps-config

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VPS Admin Stack Configuration

License: Apache 2.0 Docker Ubuntu WireGuard

Automated setup for a secure VPS with WireGuard VPN, Traefik reverse proxy, and Portainer container management.

Features

  • WireGuard VPN: Secure private network access to administration services.
  • Traefik v2: Reverse proxy with automatic HTTPS via Let's Encrypt.
  • Portainer: Web-based interface for Docker container management.
  • Website Deployment: Easy deployment of Apache-based websites with automatic SSL.
  • Minecraft Servers: Deploy and manage multiple Minecraft servers (Vanilla, Forge, Fabric, NeoForge, Paper).
  • Security: Admin services accessible only through the VPN and optional IP whitelisting.
  • Automation: Complete setup in a few commands.
  • Modularity: Add or remove services easily.

Project Structure

vps-config/
├── init.sh              # Main initialization script (run as root)
├── scripts/             # User scripts directory
│   ├── setup.sh        # Admin stack setup
│   ├── start-admin-stack.sh
│   ├── show-vpn-config.sh
│   ├── update-ufw.sh   # UFW firewall management
│   ├── new-site.sh     # Deploy new websites
│   └── new-minecraft.sh # Deploy new Minecraft servers
├── .env                # Environment configuration
└── README.md           # This file

All scripts in the scripts/ directory are automatically copied to /home/$USER_NAME/ during initialization.

Prerequisites

  • A fresh Debian or Ubuntu VPS.
  • Root access to the server.
  • A domain name pointing to the VPS.
  • Basic knowledge of Linux and Docker.

Installation

1. Clone the repository

git clone https://github.com/AlainPiallat/vps-config.git
cd vps-config

2. Configure the environment

cp .env.example .env
nano .env

Main variables:

  • USER_NAME: Linux username to create.
  • USER_EMAIL: Email used for Let's Encrypt.
  • DOMAIN: Main domain name.
  • VPN_SUBNET: VPN network (default: 10.13.13.0/24).
  • SSH_PUBLIC_KEY: Your SSH public key.

3. Initialize the system (as root)

chmod +x init.sh # Make script executable
sudo ./init.sh

This will:

  • Create the /etc/vps-config directory for shared configuration files.
  • Create the user account.
  • Install Docker and Docker Compose.
  • Set up WireGuard VPN.
  • Configure UFW and Fail2Ban.
  • Harden SSH access.
  • Generate the port registry file (/etc/vps-config/.port).
  • Copy configuration files to /etc/vps-config.

The script is idempotent and can be re-run safely.

4. Set up the admin stack (as regular user)

su USER_NAME
cd ~

./setup.sh

This will:

  • Create the ~/admin-stack directory.
  • Generate the Traefik configuration.
  • Create docker-compose.yml.
  • Prepare startup scripts.

5. Start the stack

cd ~/admin-stack
./start.sh

VPN Configuration

Once init.sh is complete, WireGuard configurations will be generated for your devices.

Display or export configurations with:

./show-vpn-config.sh

To connect:

  1. Install WireGuard on your device.
  2. Import the configuration file.
  3. Enable the VPN tunnel.

Access to Admin Services

Once connected to the VPN:

  • Traefik Dashboard: http://10.13.13.1:8080/dashboard/
  • Portainer: http://10.13.13.1:9000/

Note: Create your Portainer admin account within the first 5 minutes after startup.

Security Overview

  • Admin interfaces accessible only via VPN.
  • Automatic HTTPS certificates via Let's Encrypt.
  • Fail2Ban protection against brute-force attacks.
  • UFW firewall allowing only necessary ports.
  • SSH hardened with key-only authentication.

Configuration Management

/etc/vps-config Directory

The project creates a dedicated directory /etc/vps-config to store shared configuration files:

/etc/vps-config/
├── .env              # Environment variables (copy from project)
├── .port             # Port registry file
└── update-ufw.sh     # UFW update script

Port Registry File (.port)

The .port file is automatically generated during initialization and lists all open ports in the following format:

<port> <protocol> <service_name>

Example:

22 tcp SSH
80 tcp HTTP
443 tcp HTTPS
51820 udp WireGuard

Usage:

  • This file is used by the update-ufw.sh script to manage firewall rules.
  • To add a new port, edit /etc/vps-config/.port and run sudo /etc/vps-config/update-ufw.sh.
  • Comments can be added with # at the beginning of a line.
  • Service names with spaces are supported (e.g., 8080 tcp Web Application).

Updating Firewall Rules

To update UFW rules based on the port registry:

# Edit the port configuration
sudo nano /etc/vps-config/.port

# Apply the changes
sudo /etc/vps-config/update-ufw.sh

This will reset UFW and recreate all rules based on the .port file.

Network Architecture

Internet
    │
    ├─── Ports 80/443 ───→ Traefik ───→ Websites (auto HTTPS)
    │
    ├─── Ports 25565+ ──→ Minecraft servers (one port per server)
    │         (DNS SRV records map subdomains to each port)
    │
    └─── Port 51820 ───→ WireGuard VPN
                              │
                              └─→ 10.13.13.0/24 (VPN Network)
                                     ├─→ Traefik Dashboard (:8080)
                                     ├─→ Portainer (:9000)
                                     └─→ Minecraft RCON (VPN only)

All containers share an external Docker network named proxy, enabling secure internal routing through Traefik.

Updating the Stack

This project evolves over time. Here is how to safely pull new scripts and use new features without affecting running services.

Pulling updates

# On your local machine, in the cloned repository
git pull

# Review what changed
git log --oneline -10
git diff HEAD~1 HEAD

Deploying updated scripts to the server

New or updated scripts need to be copied to the server. Run init.sh again - it is fully idempotent and will only update what needs updating (it will not reinstall Docker, recreate users, or regenerate WireGuard keys if they already exist):

# On the server, as root
sudo ./init.sh

This re-copies all scripts from scripts/ to /home/$USER_NAME/ and refreshes /etc/vps-config/.env.

Alternatively, copy only the scripts you need manually:

scp scripts/new-minecraft.sh user@your-vps:~/new-minecraft.sh
chmod +x ~/new-minecraft.sh

Impact on running services

Component Impact of re-running init.sh
Running websites (/srv/site-*) None - containers are untouched
Running Minecraft servers (/srv/mc-*) None - containers are untouched
Admin stack (~/admin-stack) None - re-run setup.sh only if Traefik config changed
WireGuard VPN None - keys and config are preserved
UFW firewall Refreshed from /etc/vps-config/.port (no port is lost)
SSH config Preserved - original backed up with timestamp

Updating .env variables

If new variables are added to .env.example (such as MINECRAFT_PORT_START):

  1. Compare .env.example with your .env:
    diff .env.example .env
  2. Add missing variables to your .env
  3. Re-run init.sh to propagate the file to the server

Updating the admin stack (Traefik / Portainer)

If setup.sh was updated (e.g. new Traefik config):

# As regular user on the server
./setup.sh           # regenerates ~/admin-stack config files

cd ~/admin-stack
docker compose pull  # pull latest images
docker compose up -d # apply new config (zero-downtime for running sites)

Running websites and Minecraft servers are unaffected because they run in separate containers on the shared proxy network.

Troubleshooting

VPN not connecting

sudo systemctl status wg-quick@wg0
sudo journalctl -u wg-quick@wg0 -n 50

Unable to access admin services

ping 10.13.13.1
docker ps
docker compose logs traefik

Useful Commands

# Start admin stack
cd ~/admin-stack && ./start.sh

# View logs
docker compose logs -f

# Restart stack
docker compose restart

# Stop stack
docker compose down

# Check VPN status
sudo wg show

Deploying Websites

Quick Start

Deploy a new website with automatic SSL certificate:

./new-site.sh [subdomain]

Examples:

./new-site.sh blog        # Creates blog.yourdomain.com

./new-site.sh @           # Creates yourdomain.com

What it does

The new-site.sh script automatically:

  1. Creates a directory structure in /srv/site-<name>/
  2. Generates a Docker Compose configuration with Apache
  3. Creates a welcome HTML page
  4. Configures Traefik for automatic HTTPS (Let's Encrypt)
  5. Starts the container
  6. Verifies the site is accessible

Note: Sites are stored in /srv/ following Linux Filesystem Hierarchy Standard (FHS).

Directory Structure

/srv/site-blog/
├── docker-compose.yml # Docker configuration
├── Dockerfile         # Custom PHP+Apache image
├── manage.sh          # Management script
├── html/              # Website files (edit here)
│   └── index.html     # Main page
├── logs/              # Apache access and error logs
└── README.md          # Site-specific documentation

Managing Your Sites

Each site includes a manage.sh script for common operations:

cd /srv/site-blog

# Start the site
./manage.sh start

# Stop the site
./manage.sh stop

# Restart the site
./manage.sh restart

# View logs
./manage.sh logs

# Check status
./manage.sh status

Updating Content

  1. Edit files in /srv/site-<name>/html/
  2. Restart the container: cd /srv/site-<name> && ./manage.sh restart

Requirements

  • DNS record for the (sub)domain must point to your VPS IP
  • Ports 80 and 443 must be open (configured during init.sh)
  • Traefik must be running (admin stack)
  • Apache containers use port 80 internally, Traefik handles external routing

Deploying Minecraft Servers

Quick Start

Deploy a new Minecraft server with an interactive configuration wizard:

./new-minecraft.sh <folder-name>
./new-minecraft.sh @              # default server (folder: mc, url: mc.example.com)

Examples:

./new-minecraft.sh survival       # /srv/mc-survival, default subdomain: survival
./new-minecraft.sh creative       # /srv/mc-creative, default subdomain: creative
./new-minecraft.sh @              # /srv/mc-mc,       default subdomain: mc

What it does

The new-minecraft.sh script:

  1. Asks a series of questions (subdomain, server type, version, RAM, MOTD, etc.)
  2. Finds the next available port starting from MINECRAFT_PORT_START (default: 25565)
  3. Creates a directory structure in /srv/mc-<name>/
  4. Generates a docker-compose.yml using itzg/minecraft-server
  5. Registers the port in /etc/vps-config/.port and reloads UFW
  6. Starts the server
  7. Displays the DNS SRV record to create at your registrar

Supported server types

Type Description
VANILLA Official Mojang server, no mods
PAPER Performance-optimized, supports Bukkit/Spigot plugins
FABRIC Lightweight modern mod loader
FORGE Classic mod loader, widest mod ecosystem
NEOFORGE Modern fork of Forge

DNS SRV records (subdomain access)

Each server runs on a unique port. A DNS SRV record maps a subdomain to that port so players never need to type the port number.

For a server on port 25566, create this record at your DNS provider:

Type:     SRV
Name:     _minecraft._tcp.survival
Target:   yourdomain.com.
Port:     25566
Priority: 0
Weight:   5
TTL:      3600

Players then connect simply with survival.yourdomain.com.

Directory structure

/srv/mc-survival/
├── docker-compose.yml  # Docker configuration (auto-generated)
├── manage.sh           # Management script
├── server.env          # Runtime variables and RCON password (chmod 600)
├── data/               # World, configs, server.properties (persistent)
└── mods/               # .jar mod files (Forge / Fabric / NeoForge only)

Managing a Minecraft server

Each server includes a manage.sh script:

cd /srv/mc-survival

./manage.sh start               # Start the server
./manage.sh stop                # Warn players (10s) then stop
./manage.sh restart             # Restart the server
./manage.sh rebuild             # Pull latest image and restart
./manage.sh logs                # Follow server logs (Ctrl+C to exit)
./manage.sh status              # Show container status and info
./manage.sh console             # Open interactive RCON console
./manage.sh backup              # Backup world data to .tar.gz
./manage.sh backup my-save.tar.gz
./manage.sh whitelist add <player>
./manage.sh whitelist remove <player>
./manage.sh whitelist list
./manage.sh op <player>         # Give operator permissions

Adding mods (Forge / Fabric / NeoForge)

  1. Drop .jar mod files into /srv/mc-<name>/mods/
  2. Rebuild the server: cd /srv/mc-<name> && ./manage.sh rebuild

Online mode / cracked clients

During setup, the script asks whether to allow offline (cracked) clients:

  • Online mode ON (default): players must have a valid Mojang/Microsoft account. Skins and UUIDs are authenticated by Mojang servers.
  • Online mode OFF: anyone can connect without an official account. This is useful for private servers where some participants do not own the game, but it disables Mojang authentication entirely.

This can be changed later by editing ONLINE_MODE in the server's docker-compose.yml and running ./manage.sh rebuild.

Adding Your Own Services

You can deploy your own applications behind Traefik by connecting them to the proxy network and adding the required Traefik labels.

Example:

services:
  myapp:
    image: nginx:alpine
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.myapp.rule=Host(`myapp.yourdomain.com`)"
      - "traefik.http.routers.myapp.entrypoints=websecure"
      - "traefik.http.routers.myapp.tls.certresolver=letsencrypt"

networks:
  proxy:
    external: true

Available Scripts

After initialization, the following scripts are available in your home directory:

Script Description
setup.sh Set up the admin stack (Traefik + Portainer)
start-admin-stack.sh Start the admin stack containers
show-vpn-config.sh Display WireGuard VPN configurations
new-site.sh Deploy a new Apache website with automatic SSL
new-minecraft.sh Deploy a new Minecraft server (interactive setup)
update-ufw.sh Update firewall rules (requires sudo)

Configuration Files

User Directory (~/)

  • Scripts and utilities for day-to-day operations

System Directory (/etc/vps-config/)

  • .env - Environment variables
  • .port - Port registry for firewall management
  • update-ufw.sh - Firewall management script

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Disclaimer

This configuration is provided as-is. You are responsible for reviewing and adapting it to your specific use case.

Acknowledgments

  • Based on the work of thienhaole92.
  • Thanks to the Traefik and WireGuard communities.

Contact

Alain Piallat - GitHub

About

Complete configuration to deploy a secure services stack on VPS.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages