Setting up Jenkins on Proxmox in a home lab
Comprehensive guide to deploying Jenkins on Proxmox in a home lab, featuring multi-agent setup with Linux and macOS, Docker integration, secure SSH configuration, and best practices for scalable, cross-platform CI/CD automation.
Jenkins is a powerful automation server used to build, test, and deploy software. In many setups, the Jenkins master orchestrates builds, but doesn’t perform them directly-builds run on agents or slaves. This article walks through how to deploy Jenkins in a Proxmox‑based home lab with a reverse proxy, where the master delegates all builds to two slaves: one Linux LXC (Docker‑capable), and one macOS SSH slave.
🚀 Prerequisites
- A Proxmox VE hypervisor running Debian‑based host.
- Nginx Proxy Manager (or equivalent) configured to expose the Jenkins master via HTTPS.
- Basic familiarity with Proxmox, LXC containers, macOS terminal, SSH.
- SSH keypair for connecting master → slaves.
- Docker installed on the LXC slave.
🎯 Overview of the Architecture
- Jenkins master runs in a lightweight container (LXC) or Docker, but only handles coordination, plugins, user interface, and job scheduling.
- Slave #1: Linux LXC container, Docker installed → used for Docker‑based builds, pipelines, container testing.
- Slave #2: A macOS host (could be a Mac Mini or a VM) configured as an SSH agent to run macOS‑specific jobs (e.g. iOS builds, multi‑platform tools).
- Reverse proxy (Nginx Proxy Manager) handles public access and TLS termination for the Jenkins master UI.
⚙️ Setting Up Jenkins Master (LXC or Docker)
- Create an LXC container in Proxmox (Debian/Ubuntu preferred).
Install Java (OpenJDK 17 or 21 as supported):
1
apt update && apt install -y openjdk-17-jdk-headless
Install Jenkins (generic War or apt repo):
1 2 3
wget -qO - https://pkg.jenkins.io/debian-stable/jenkins.io.key | apt-key add - add-apt-repository "deb https://pkg.jenkins.io/debian-stable binary/" apt update && apt install -y jenkins
Configure Jenkins to run with no built‑in executors:
- Navigate to Manage Jenkins → Configure System.
- Set # of executors to 0.
- Open ports if necessary inside the LXC: ensure port 8080 is reachable by the proxy only.
- Point Nginx Proxy Manager (or your reverse proxy) to this LXC’s internal IP and port 8080. Set up TLS, basic auth, and routing.
🔧 Configuring Jenkins Slave #1 (Linux LXC + Docker)
- Provision a new LXC container, e.g. Ubuntu.
Install Docker:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
apt-get update apt-get install ca-certificates curl install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc # Add the repository to Apt sources: echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \ tee /etc/apt/sources.list.d/docker.list > /dev/null apt-get update apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Add user (e.g.
jenkins
) to Docker group:1 2
useradd -m -s /bin/bash jenkins usermod -aG docker jenkins
- Enable SSH and add the Jenkins master’s public key to
~jenkins/.ssh/authorized_keys
. In the Jenkins master UI, go to Manage Nodes & Clouds → New Node → configure:
- Launch via SSH
- Host: LXC’s IP
- Credentials: private key of the master
- Remote FS root:
/home/jenkins
- Confirm that the agent connects successfully.
Now in pipelines or jobs, you can configure to run on this label and leverage Docker builds:
1 2 3 4 5 6 7 8 9 10
pipeline { agent { label 'docker-agent' } stages { stage('Build') { steps { sh 'docker build -t myapp:latest .' } } } }
🍎 Configuring Jenkins Slave #2 (macOS via SSH)
- On the macOS machine, enable Remote Login (System Preferences → Sharing → Remote Login).
- Create a Jenkins user or choose a dedicated user, and install Homebrew, Xcode tools, etc.
- Add the master’s SSH public key to
~jenkins/.ssh/authorized_keys
. - Ensure required tools are installed (Java agent jar, Xcode Command Line Tools, etc.).
On the Jenkins master UI, add a new node:
- Launch via SSH
- Host: macOS IP
- Credentials: same private key or separate credential
- Remote FS root: e.g.
/Users/jenkins
- Assign a label like
macos-agent
, so jobs requiring macOS can run there. Sample pipeline specifying macOS agent:
1 2 3 4 5 6 7 8 9 10
pipeline { agent { label 'macos-agent' } stages { stage('Test') { steps { sh 'swift --version' } } } }
🧪 Testing the Multi‑Agent Setup
Create or update Jenkins pipeline jobs:
- One using
docker-agent
label → runs on the Linux LXC Docker slave. - One using
macos-agent
→ runs on the macOS host.
- One using
- Trigger builds via Jenkins UI accessible through your reverse proxy domain (e.g.
jenkins.home.mydomain.com
). Verify:
- The master shows executors 0, and builds go to agents.
- Logs show build steps execute on the respective machines.
- Docker containers build/run on LXC; macOS tools run on the macOS node.
🔐 Security & Maintenance Tips
- Use SSH key authentication only-disable password login.
- Restrict traffic to agents: only master’s host should SSH in.
- Keep Jenkins and plugins up to date using in‑UI update centers.
- Regularly update LXC base images, host OS, and macOS software.
- Backup Jenkins config and credentials with [Jenkins backup plugins] or manual file backups.
🧼 Clean Code Sample: Docker Build Jenkinsfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
pipeline {
agent { label 'docker-agent' }
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build & Test') {
steps {
sh '''
docker build -t myapp:${env.BUILD_NUMBER} .
docker run --rm myapp:${env.BUILD_NUMBER} ./runTests.sh
'''
}
}
}
}
This snippet follows clean code guidelines: readable stages, meaningful labels, minimal inline scripts, and environment‑driven versioning.
📋 Summary Cheat‑Sheet
Component | Role | Label |
---|---|---|
Jenkins Master | Coordinates builds, no actual execution | (none, executors = 0) |
Linux LXC Slave | Runs Docker‑based builds | docker-agent |
macOS Slave | Executes macOS‑specific jobs | macos-agent |
Reverse Proxy (NGM) | TLS, public access routing to master | - |
Final Thoughts
✅ Setting up Jenkins with master coordinates only and agents doing all the work gives flexibility, isolation, and performance in a home‑lab context. ✅ Proxmox LXC is lightweight and ideal for consistent Linux build environments, especially with Docker. ✅ Adding a macOS SSH agent allows testing or building on Apple platforms when needed. ✅ Proper SSH key management, network restrictions, and regular updates ensure stability and security.
By following this setup, you gain a modular, maintainable, and secure CI platform at home. If you’re building cross‑platform tools, iOS apps, or containerized services, this architecture scales nicely.