289 lines
8.1 KiB
Markdown
289 lines
8.1 KiB
Markdown
# Step-CA Docker Stack
|
|
|
|
A Docker Compose setup for deploying [Smallstep CA](https://smallstep.com/certificates/) (step-ca) with PostgreSQL backend support for certificate management and PKI infrastructure.
|
|
|
|
## Features
|
|
|
|
- **Automated Initialization**: Automatic step-ca setup with optional SSH and ACME support
|
|
- **PostgreSQL Backend**: Uses PostgreSQL as the primary database (replacing the default Badger)
|
|
- **Health Checks**: Built-in health checks for PostgreSQL service
|
|
- **Customizable Configuration**: Full environment variable support for customization
|
|
- **Docker Build**: Custom Dockerfile with jq for JSON manipulation
|
|
- **Remote Management**: Support for remote management capabilities
|
|
- **Admin Provisioner**: Built-in JWK admin provisioner for certificate issuance
|
|
|
|
## Prerequisites
|
|
|
|
- Docker
|
|
- Docker Compose
|
|
- Basic knowledge of step-ca and PKI concepts
|
|
|
|
## Quick Start
|
|
|
|
### 1. Clone and Setup
|
|
|
|
```bash
|
|
cd /path/to/step-ca
|
|
cp .env.example .env
|
|
# Edit .env with your specific configuration
|
|
```
|
|
|
|
### 2. Configure Environment
|
|
|
|
Edit `.env` file with your desired configuration:
|
|
|
|
```env
|
|
# PostgreSQL Configuration
|
|
POSTGRES_PASSWORD=your_secure_password
|
|
|
|
# Step-CA Configuration
|
|
STEP_CA_IP=192.168.1.100
|
|
STEP_CA_PORT=9000
|
|
STEP_CA_NAME=My Internal CA
|
|
STEP_CA_ISSUER=CN=My Internal CA, O=MyOrg, C=US
|
|
STEP_CA_DNS_NAMES=ca.example.com,ca.internal,pki.local
|
|
STEP_CA_PROVISIONER=admin-provisioner
|
|
STEP_CA_ADMIN_SUBJECT=admin@example.com
|
|
STEP_CA_SSH=true
|
|
STEP_CA_ACME=true
|
|
STEP_CA_REMOTE_MANAGEMENT=true
|
|
|
|
# DNS Configuration
|
|
DNS_1=8.8.8.8
|
|
DNS_2=8.8.4.4
|
|
DNS_SEARCH_1=example.com
|
|
DNS_SEARCH_2=internal.local
|
|
```
|
|
|
|
### 3. Initialize Secrets
|
|
|
|
Create the required secret files. These are mounted as Docker secrets at `/run/secrets/` inside containers:
|
|
|
|
```bash
|
|
mkdir -p secrets
|
|
|
|
echo "your_secure_password" > secrets/postgres_password.txt
|
|
|
|
echo "your_ca_password" > secrets/step_pwd.txt
|
|
|
|
chmod 600 secrets/*.txt
|
|
```
|
|
|
|
**Important**: These secrets are automatically mounted by Docker Compose:
|
|
- `secrets/postgres_password.txt` → `/run/secrets/postgres_password`
|
|
- `secrets/step_pwd.txt` → `/run/secrets/password`
|
|
|
|
or just `make configure`
|
|
|
|
### 4. Start the Stack
|
|
|
|
```bash
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
### 5. Verify Deployment
|
|
|
|
```bash
|
|
docker-compose logs -f step-ca
|
|
|
|
docker-compose ps
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Environment Variables
|
|
|
|
All configuration is managed through the `.env` file. Key variables:
|
|
|
|
| Variable | Description | Default | Example |
|
|
|----------|-------------|---------|---------|
|
|
| `POSTGRES_PASSWORD` | PostgreSQL password | - | `secure_pass_123` |
|
|
| `STEP_CA_IP` | IP address for CA service | `127.0.0.1` | `192.168.1.100` |
|
|
| `STEP_CA_PORT` | Port for CA service | `9000` | `9000` |
|
|
| `STEP_CA_NAME` | CA name | `Default CA` | `Company Internal CA` |
|
|
| `STEP_CA_ISSUER` | CA issuer certificate DN | - | `CN=My CA, O=Org, C=US` |
|
|
| `STEP_CA_DNS_NAMES` | DNS names for CA cert | `localhost,ca.local` | `ca.example.com,ca.internal` |
|
|
| `STEP_CA_PROVISIONER` | Provisioner name | `admin` | `admin-provisioner` |
|
|
| `STEP_CA_ADMIN_SUBJECT` | Admin email address | `admin@example.com` | `ca-admin@company.com` |
|
|
| `STEP_CA_SSH` | Enable SSH support | `true` | `true` or `false` |
|
|
| `STEP_CA_ACME` | Enable ACME support | `true` | `true` or `false` |
|
|
| `STEP_CA_REMOTE_MANAGEMENT` | Enable remote management | `true` | `true` or `false` |
|
|
| `DNS_1`, `DNS_2` | DNS servers | `8.8.8.8`, `8.8.4.4` | `1.1.1.1`, `1.0.0.1` |
|
|
| `DNS_SEARCH_1-3` | DNS search domains | `localhost,local,internal` | `example.com,internal.local` |
|
|
|
|
## Service Details
|
|
|
|
### PostgreSQL Service
|
|
- **Image**: `postgres:16-alpine`
|
|
- **Database**: `stepca`
|
|
- **User**: `stepca`
|
|
- **Health Check**: PostgreSQL readiness probe every 10 seconds
|
|
- **Persistent Storage**: `postgres-data` volume
|
|
|
|
### Step-CA Service
|
|
- **Build**: Custom image based on `smallstep/step-ca`
|
|
- **Port**: Configurable via `STEP_CA_PORT` (default: 9000)
|
|
- **Database Migration**: Automatic transition from Badger to PostgreSQL
|
|
- **Persistent Storage**: `stepca-data` volume for certificates and configuration
|
|
|
|
## Initialization Flow
|
|
|
|
1. **First Run**: If `ca.json` doesn't exist:
|
|
- Step-ca performs automated initialization with Badger database
|
|
- Uses Docker secret from `/run/secrets/password` for key encryption
|
|
- Generates root, intermediate, and SSH certificates
|
|
- Creates admin provisioner
|
|
|
|
2. **PostgreSQL Migration**:
|
|
- Configuration is migrated from Badger to PostgreSQL
|
|
- Database connection details are stored in `ca.json`
|
|
- Marker file created to prevent re-initialization
|
|
|
|
3. **Subsequent Runs**:
|
|
- Step-ca starts directly with PostgreSQL backend
|
|
- Uses the same Docker secret for decrypting keys
|
|
- No re-initialization occurs (marker file prevents this)
|
|
|
|
|
|
## File Structure
|
|
|
|
```
|
|
step-ca/
|
|
├── compose.yaml # Docker Compose configuration
|
|
├── Dockerfile # Custom Docker image build
|
|
├── init.sh # Initialization script
|
|
├── .env.example # Environment variables template
|
|
├── .gitignore # Git ignore rules
|
|
├── config/
|
|
│ └── ca.json # Step-ca configuration (generated)
|
|
├── secrets/
|
|
│ ├── postgres_password.txt
|
|
│ └── step_pwd.txt
|
|
└── README.md # This file
|
|
```
|
|
|
|
|
|
## Usage Examples
|
|
|
|
### Access Step-CA Admin Interface
|
|
|
|
Once the container is running, you can interact with step-ca:
|
|
|
|
```bash
|
|
# Enter the container
|
|
docker-compose exec step-ca sh
|
|
|
|
# List certificates
|
|
step certificate list
|
|
|
|
# Get CA fingerprint
|
|
step certificate fingerprint /home/step/certs/root_ca.crt
|
|
```
|
|
|
|
### Request a Certificate via JWK Provisioner
|
|
|
|
```bash
|
|
# From inside the container, using the mounted Docker secret
|
|
docker-compose exec step-ca sh -c \
|
|
'step ca certificate --provisioner=admin --provisioner-password-file=/run/secrets/password \
|
|
"my-service.example.com" /tmp/cert.pem /tmp/key.pem'
|
|
|
|
# Or from the host with your CA password
|
|
step ca certificate --provisioner=admin \
|
|
"my-service.example.com" cert.pem key.pem
|
|
```
|
|
|
|
### ACME Client Setup
|
|
|
|
If ACME is enabled, configure your ACME client:
|
|
|
|
```
|
|
CA URL: https://ca.example.com:9000
|
|
Directory: https://ca.example.com:9000/acme/acme/directory
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### PostgreSQL Connection Fails
|
|
|
|
```bash
|
|
# Check PostgreSQL logs
|
|
docker-compose logs postgres
|
|
|
|
# Verify database exists
|
|
docker-compose exec postgres psql -U stepca -d stepca -c "\dt"
|
|
```
|
|
|
|
### Step-CA Won't Start
|
|
|
|
```bash
|
|
# Check step-ca logs
|
|
docker-compose logs step-ca
|
|
|
|
# Verify configuration
|
|
docker-compose exec step-ca cat /home/step/config/ca.json
|
|
```
|
|
|
|
### Remove and Reset
|
|
|
|
To completely reset the environment:
|
|
|
|
```bash
|
|
# Stop and remove containers
|
|
docker-compose down
|
|
|
|
# Remove data volumes
|
|
docker volume rm ca-stepca-data ca-postgres-data
|
|
|
|
# Restart fresh
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
## Security Considerations
|
|
|
|
- **Secret Management**: Store passwords in `secrets/` directory and add to `.gitignore`
|
|
- **Network**: Use internal Docker network for PostgreSQL communication
|
|
- **Firewall**: Restrict access to port 9000 from trusted networks only
|
|
- **TLS**: Ensure step-ca certificates are properly validated by clients
|
|
- **Backups**: Regularly backup the `stepca-data` and `postgres-data` volumes
|
|
|
|
## Ports and Networks
|
|
|
|
- **Step-CA Port**: 9000 (configurable)
|
|
- **PostgreSQL Port**: 5432 (internal only)
|
|
- **Network**: `ca-internal` (internal Docker bridge)
|
|
|
|
## Debugging
|
|
|
|
Enable verbose logging by modifying the init script:
|
|
|
|
```bash
|
|
# Add to init.sh
|
|
set -x # Enable debug output
|
|
```
|
|
|
|
View real-time logs:
|
|
|
|
```bash
|
|
docker-compose logs -f step-ca
|
|
docker-compose logs -f postgres
|
|
```
|
|
|
|
## Related Documentation
|
|
|
|
- [Step-CA Documentation](https://smallstep.com/docs/step-ca)
|
|
- [Step CLI Reference](https://smallstep.com/docs/step-cli)
|
|
- [Docker Compose Documentation](https://docs.docker.com/compose/)
|
|
- [PostgreSQL Documentation](https://www.postgresql.org/docs/)
|
|
|
|
## Support
|
|
|
|
For issues with step-ca, refer to:
|
|
- [Step-CA GitHub](https://github.com/smallstep/certificates)
|
|
- [Step Community Discord](https://u.step.sm/discord)
|
|
- [Step Community Discussions](https://github.com/smallstep/certificates/discussions)
|
|
|
|
## License
|
|
|
|
This Docker Compose stack follows the licensing of Smallstep and individual components.
|