AWS Deployment
Deploy Artifact Keeper on a single EC2 instance using Docker Compose. The AMI comes with Docker pre-installed, all images pre-pulled, and a first-boot service that generates secrets and starts everything automatically.
Architecture
┌──────────────────────────────────────────────────┐│ EC2 Instance ││ ││ ┌───────────┐ ││ │ Nginx │ (host — handles SSL/TLS) ││ │ (80/443) │ ││ └─────┬─────┘ ││ │ ││ ┌─────▼──────────── Docker Compose ───────────┐ ││ │ │ ││ │ ┌──────────┐ ┌──────────────────────────┐ │ ││ │ │ Frontend │ │ Backend (8080) │ │ ││ │ │ (3000) │ └────────┬─────────────────┘ │ ││ │ └──────────┘ │ │ ││ │ ┌─────────┼──────────┐ │ ││ │ ┌─────▼───┐ ┌───▼─────┐ ┌─▼──────┐ │ ││ │ │Postgres │ │Meili- │ │ Trivy │ │ ││ │ │ (5432) │ │search │ │ (8090) │ │ ││ │ └─────────┘ └─────────┘ └────────┘ │ ││ └──────────────────────────────────────────────┘ ││ ││ /data/ (EBS gp3 volume) │└──────────────────────────────────────────────────┘Nginx runs on the host for SSL termination. All application services run as Docker containers managed by Docker Compose. Data is persisted to /data/ on a dedicated EBS volume.
Prerequisites
- AWS account with permissions to launch EC2 instances
- An EC2 key pair for SSH access
- AWS CLI configured (
aws configure)
Option 1: Pre-Built AMI (Quickest)
Launch the official Artifact Keeper AMI directly from the AWS console or CLI.
Find the AMI
Check the latest release for the AMI ID, or search in the EC2 console:
aws ec2 describe-images \ --owners self \ --filters "Name=name,Values=artifact-keeper-*" \ --query 'Images | sort_by(@, &CreationDate) | [-1].[ImageId,Name]' \ --output tableLaunch an Instance
aws ec2 run-instances \ --image-id ami-0123456789abcdef0 \ --instance-type t3.medium \ --key-name my-key-pair \ --security-group-ids sg-abc123 \ --block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":30,"VolumeType":"gp3"}}]' \ --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=artifact-keeper}]' \ --query 'Instances[0].InstanceId' \ --output textRetrieve Credentials
On first boot, the instance generates random credentials for all services. SSH in to retrieve them:
ssh -i ~/.ssh/my-key-pair.pem ubuntu@<PUBLIC_IP>sudo cat /opt/artifact-keeper/.credentialsOutput:
===================================== Artifact Keeper Credentials=====================================
Access URL: http://<PUBLIC_IP>
Database Password: <generated>Meilisearch Key: <generated>JWT Secret: <generated>
Docker Compose Dir: /opt/artifact-keeper
Manage services: cd /opt/artifact-keeper docker compose ps docker compose logs -f backend docker compose restart
=====================================Open http://<PUBLIC_IP> in your browser to access the UI.
Option 2: Terraform (Recommended for Production)
The Terraform module provisions the full infrastructure: VPC, security groups, IAM roles, EC2 instance, and a dedicated EBS data volume.
1. Clone the Repository
git clone https://github.com/artifact-keeper/artifact-keeper.gitcd artifact-keeper/deploy/aws/terraform2. Configure Variables
cp terraform.tfvars.example terraform.tfvarsEdit terraform.tfvars:
ami_id = "ami-0123456789abcdef0" # From latest releaseaws_region = "us-east-1"instance_type = "t3.medium"key_name = "my-key-pair"
# Restrict SSH to your IPallowed_ssh_cidrs = ["203.0.113.0/32"]
# Optional: auto-SSL with Let's Encrypt# domain = "artifacts.example.com"# admin_email = "admin@example.com"
# Artifact storage volume (GB)data_volume_size = 1003. Deploy
terraform initterraform planterraform apply4. Access Your Instance
Terraform outputs everything you need:
terraform output url# http://54.123.45.67
terraform output ssh_command# ssh -i ~/.ssh/my-key-pair.pem ubuntu@54.123.45.67
terraform output credentials_command# ssh -i ~/.ssh/my-key-pair.pem ubuntu@54.123.45.67 'sudo cat /opt/artifact-keeper/.credentials'5. Tear Down
terraform destroyOption 3: Build Your Own AMI with Packer
Use the Packer template to build a custom AMI with your own modifications.
1. Install Packer
# macOSbrew install hashicorp/tap/packer
# Ubuntu/Debiancurl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp.gpgecho "deb [signed-by=/usr/share/keyrings/hashicorp.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" \ | sudo tee /etc/apt/sources.list.d/hashicorp.listsudo apt-get update && sudo apt-get install packer2. Configure the Build
cd deploy/aws/packercp variables.auto.pkrvars.hcl.example variables.auto.pkrvars.hclEdit variables.auto.pkrvars.hcl:
artifact_keeper_version = "0.2.0"aws_region = "us-east-1"instance_type = "t3.medium"
# Copy to additional regions# ami_regions = ["us-west-2", "eu-west-1"]3. Build
packer init .packer validate .packer build .Packer will:
- Launch a temporary EC2 instance from Ubuntu 24.04
- Install Docker, Nginx, and certbot
- Copy the Docker Compose file and pull all container images
- Configure systemd services for first-boot and compose
- Snapshot the instance as a new AMI
- Terminate the temporary instance
The AMI ID is printed at the end of the build. Use it with the Terraform module or launch directly.
Customizing the Build
The provisioning scripts are in deploy/aws/scripts/:
| Script | Purpose |
|---|---|
01-docker.sh | Install Docker, Nginx, certbot, firewall |
02-artifact-keeper.sh | Copy compose file, pull images, configure systemd |
99-cleanup.sh | Remove caches and SSH keys for clean AMI |
Supporting files:
| File | Purpose |
|---|---|
docker-compose.yml | Production compose with GHCR images |
nginx-host.conf | Host Nginx config for SSL termination |
first-boot.sh | Generate secrets, configure Nginx, optional SSL |
Modify any file before building to customize the installation.
Post-Deployment
Configure SSL with Let’s Encrypt
If you didn’t set a domain during launch, you can configure SSL manually:
ssh -i ~/.ssh/my-key-pair.pem ubuntu@<PUBLIC_IP>
# Update Nginx server_namesudo sed -i 's/server_name _;/server_name artifacts.example.com;/' \ /etc/nginx/sites-available/artifact-keepersudo nginx -t && sudo systemctl reload nginx
# Request certificatesudo certbot --nginx -d artifacts.example.com \ --non-interactive --agree-tos -m admin@example.com --redirectCertbot automatically renews certificates via a systemd timer.
Configure Package Managers
Once running, configure your package managers to point at the instance. See the Package Formats Overview for client configuration guides.
Example — configure npm:
npm config set registry http://<YOUR_IP_OR_DOMAIN>/npm/my-npm-repo/npm login --registry http://<YOUR_IP_OR_DOMAIN>/npm/my-npm-repo/Check Service Status
ssh -i ~/.ssh/my-key-pair.pem ubuntu@<PUBLIC_IP>
# Container statuscd /opt/artifact-keeperdocker compose ps
# Artifact Keeper logsdocker compose logs -f backend
# All logsdocker compose logs -f
# Health checkcurl http://localhost/healthBackup
Artifacts are stored on the EBS data volume at /data/storage. Create EBS snapshots for point-in-time backups:
# Find the volume IDINSTANCE_ID=$(aws ec2 describe-instances \ --filters "Name=tag:Name,Values=artifact-keeper" \ --query 'Reservations[0].Instances[0].InstanceId' --output text)
VOLUME_ID=$(aws ec2 describe-volumes \ --filters "Name=attachment.instance-id,Values=${INSTANCE_ID}" \ "Name=tag:Name,Values=*data*" \ --query 'Volumes[0].VolumeId' --output text)
# Create snapshotaws ec2 create-snapshot \ --volume-id "$VOLUME_ID" \ --description "artifact-keeper-backup-$(date +%Y%m%d)" \ --tag-specifications "ResourceType=snapshot,Tags=[{Key=Name,Value=artifact-keeper-backup}]"Instance Sizing
| Workload | Instance Type | vCPU | RAM | Artifacts |
|---|---|---|---|---|
| Small team (< 20 devs) | t3.medium | 2 | 4 GB | Up to 100 GB |
| Medium team (20–100 devs) | t3.large | 2 | 8 GB | Up to 500 GB |
| Large team (100+ devs) | m6i.xlarge | 4 | 16 GB | 1 TB+ |
All instances use gp3 EBS volumes. Increase the data_volume_size Terraform variable for more artifact storage.
Troubleshooting
First-boot didn’t complete
# Check first-boot logsudo journalctl -u artifact-keeper-first-boot
# Re-run manuallysudo /opt/artifact-keeper/first-boot.shArtifact Keeper won’t start
cd /opt/artifact-keeper
# Check container statusdocker compose ps
# Check backend logsdocker compose logs backend
# Check if database is healthydocker compose logs postgres
# Restart everythingdocker compose down && docker compose up -dCan’t connect to the instance
- Verify the security group allows inbound HTTP (port 80) and HTTPS (port 443)
- Check that the instance has a public IP or Elastic IP
- Confirm UFW is allowing traffic:
sudo ufw status
SSL certificate issues
# Test renewalsudo certbot renew --dry-run
# Force renewalsudo certbot renew --force-renewalSee Also
- Docker Compose Deployment — Containerized deployment
- Kubernetes Deployment — Cluster deployment
- Configuration — Environment variables reference
- Backup & Recovery — Backup strategies