A Certificate Authority (CA) system with network isolation, authentication, and secure access controls.
The project consists of several interconnected components:
- Backend: Certificate Authority server that issues and manages certificates
- Frontend: Nginx web server with JWT authentication module
- Database: MySQL database for storing CA data
- Logging: Centralized logging server
- Router: Network router providing isolation between network segments
- Jumphost: WireGuard VPN server for secure remote access
- Client: Test client for accessing the system
- Backup: Backup service for CA data
The system uses Kathara for network emulation, allowing precise control over network topology and isolation between components.
The project uses a two-tier Makefile system to manage configuration and deployment:
The root Makefile orchestrates the build process through several targets:
The main build command that:
- Generates certificates and keys (via
.certs/Makefile) - Runs
configureto prepare all host configurations - Delegates to the Kathara Makefile to build the Docker images
Starts the Kathara lab environment using the built images.
This target is the heart of the configuration system:
- Generates certificates, WireGuard configs, and SSH keys via
.certs/Makefile - Creates
generated/directories for each host (backend, frontend, router, jumphost, client, backup, database, logging) - Copies required configuration files into each
host/generated/directory - Uses stamp files (
host/generated/.configured) to track completion
Stops and cleans up the Kathara lab environment.
Opens a tmux session with terminals for all lab machines.
Removes all generated configuration files and stamp files from host/generated/ directories. This forces a complete reconfiguration on the next make configure or make build.
The .configured targets serve as dependency tracking in Make:
- Each
host/generated/.configuredtarget depends on the specific configuration files that host needs - Make only copies files if dependencies are newer than the stamp file
- This ensures configuration files are up-to-date before Docker images are built
- The stamp files are created after successful copying to mark completion
The files in host/generated/ directories are sourced during Docker image builds:
- Each Dockerfile uses
COPY generated/...commands to copy files into the container image - For example:
backend/Dockerfilecopiesgenerated/sysadmin.id_rsa.pubandgenerated/sshd_configfrontend/Dockerfilecopies multiple files including certificates, JWT keys, and SSH configsjumphost/Dockerfilecopies WireGuard configs and SSH keys
Kathara volumes don't work with individual files - they require directories. Instead of trying to mount individual configuration files at runtime, we:
- Copy all necessary files into
host/generated/directories during the build phase - Embed these files directly into Docker images via
COPYcommands - This ensures all configuration is available when containers start, regardless of Kathara's volume limitations
Handles the actual deployment:
- Image Building: Uses Docker Compose to build all container images
- Lab Management: Uses Kathara to start, stop, and manage the network lab environment
- Terminal Access: Provides tmux-based terminal access to all lab machines
-
Certificates: The
make buildcommand automatically generates certificates, but you can also generate them manually:cd .certs/ make certsThis generates:
- CA certificate and key (
ca.crt,ca.key) - Nginx server certificate and key (
nginx.crt,nginx.key) - Client certificates for
alice,bobandcharliein PKCS#12 format (alice.p12,bob.p12,charlie.p12) - Machine certificates for backend, frontend, database, etc.
- JWT keys for authentication
- WireGuard configuration files
- SSH keys for sysadmin access
- CA certificate and key (
-
Browser Setup (for local development):
- Import
ca.crtinto your browser's trusted CAs - Import
alice.p12orbob.p12into your browser (password:password) for mTLS authentication
- Import
make build
make upThis sequence:
- Generates certificates and keys (if not already present)
- Configures all hosts by copying files to
host/generated/directories - Builds all Docker images using Docker Compose
- Starts the Kathara lab with network isolation
make downThis cleans up all Kathara lab machines and wipes the lab environment.
make tmuxOpens a tmux session with terminals for all lab machines, allowing you to interact with each component.
make clean-configureRemoves all generated configuration files and stamp files from host/generated/ directories. This forces a complete reconfiguration on the next make configure or make build. Useful when you've changed source configuration files and want to ensure they're re-copied.
The Makefile automatically manages configuration files for each host:
- Backend: SSH public key, SSH daemon config, machine certificates, CA certificates, JWT keys, and archive keys
- Frontend: SSH key, SSH config, Nginx certificates (
nginx.crt,nginx.key), JWT public key, client certificates, and machine intermediate certificate - Router: SSH public key, SSH server config, and supervisord config
- Jumphost: SSH public key, WireGuard server config (
wg0-server.conf), SSH server config, and supervisord config (has its ownsshd_config) - Client: SSH private key (
sysadmin.id_rsa), WireGuard client config (wg0-client.conf), CA certificate, and client certificates - Backup: SSH public key, SSH daemon config, SSH server config, and supervisord config
- Database: SSH public key, SSH daemon config, SSH server config, supervisord config, machine certificate chain, and database certificates
- Logging: SSH public key, SSH daemon config, SSH server config, supervisord config, machine certificate chain, and logging certificates
All files are copied from their source locations (.certs/, base/) into host/generated/ directories, which are then used during Docker image builds.
The easiest way to develop and test changes:
make down clean-configure build up tmuxThis command sequence:
make down: Stops and cleans up the current lab environmentmake clean-configure: Removes all generated configuration files, forcing a fresh configurationmake build: Generates certificates, configures all hosts, and builds imagesmake up: Starts the labmake tmux: Opens terminals for all lab machines for interactive testing
This ensures you start with a clean slate and all configuration files are properly regenerated and copied.
The Kathara lab defines the following network segments:
- INTERNET: External network where clients connect
- JUMPHOST: Network segment for the WireGuard jumphost
- FRONTEND: Network segment for the frontend
- INTERNAL: Internal network for backend services
The router connects all segments and provides network isolation.
.
├── backend/ # CA backend service
│ └── generated/ # Generated config files (created by Makefile)
├── frontend/ # Nginx frontend with JWT auth
│ └── generated/ # Generated config files (created by Makefile)
├── database/ # MySQL database
│ └── generated/ # Generated config files (created by Makefile)
├── logging/ # Logging server
│ └── generated/ # Generated config files (created by Makefile)
├── router/ # Network router
│ └── generated/ # Generated config files (created by Makefile)
├── jumphost/ # WireGuard VPN server
│ └── generated/ # Generated config files (created by Makefile)
├── client/ # Test client
│ └── generated/ # Generated config files (created by Makefile)
├── backup/ # Backup service
│ └── generated/ # Generated config files (created by Makefile)
├── base/ # Common configuration files (sshd_config, etc.)
├── .certs/ # Certificate generation and management
├── kathara/ # Kathara lab configuration
├── Makefile # Root Makefile for configuration management
└── docker-compose.yml # Docker Compose file for image building
- The Docker Compose file is used only for building images, not for running the services
- Services are actually run using Kathara for network emulation
- Configuration files are automatically synchronized into
host/generated/directories before building - The
generated/directories are created by the Makefile and should not be committed to version control - The system requires certificates to be generated before first use (handled automatically by
make build) - Kathara volumes limitation: Since Kathara volumes don't work with individual files, all configuration is embedded in Docker images via the
generated/directory approach