Infrastructure & Config Management Guide
Artifact Keeper provides native support for infrastructure-as-code and configuration management package formats.
Terraform
Endpoint
Terraform operations use the /terraform/{repo} endpoint:
http://localhost:8080/terraform/{repo}Alternative formats:
- Key:
terraform - Alias:
opentofu
Clients
Compatible with:
terraform- HashiCorp Terraformtofu- OpenTofu (open-source Terraform fork)
Module Configuration
Configure Module Source
In your Terraform configuration:
module "vpc" { source = "localhost:8080/terraform/modules/vpc" version = "1.0.0"}Registry Block
Configure Terraform to use Artifact Keeper as a module source:
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } }}
module "networking" { source = "localhost:8080/terraform/modules/networking" version = ">= 1.0.0"}Provider Mirror Configuration
Configure Terraform to use Artifact Keeper as a provider mirror.
CLI Configuration
Create or edit ~/.terraformrc (Linux/macOS) or %APPDATA%/terraform.rc (Windows):
provider_installation { network_mirror { url = "http://localhost:8080/terraform/providers/" }}With Authentication
provider_installation { network_mirror { url = "http://localhost:8080/terraform/providers/" include = ["registry.terraform.io/*/*"] }}
credentials "localhost:8080" { token = "your-api-token"}Publishing Modules
Module Structure
Standard Terraform module structure:
terraform-vpc-aws/├── main.tf├── variables.tf├── outputs.tf├── README.md├── LICENSE└── examples/ └── basic/ └── main.tfModule Metadata
Create terraform-registry-manifest.json:
{ "version": 1, "metadata": { "name": "vpc", "namespace": "mycompany", "provider": "aws", "version": "1.0.0", "source": "https://github.com/mycompany/terraform-vpc-aws" }}Publishing via HTTP
# Create module archivetar -czf terraform-vpc-aws-1.0.0.tar.gz -C terraform-vpc-aws .
# Upload to registrycurl -X PUT \ -H "Authorization: Bearer your-token" \ -F "file=@terraform-vpc-aws-1.0.0.tar.gz" \ http://localhost:8080/terraform/modules/mycompany/vpc/aws/1.0.0Using Terraform Init
# Initialize and install modulesterraform init
# Upgrade modulesterraform init -upgradeVersion Constraints
In module sources:
# Exact versionmodule "vpc" { source = "localhost:8080/terraform/modules/vpc" version = "1.0.0"}
# Version rangemodule "vpc" { source = "localhost:8080/terraform/modules/vpc" version = ">= 1.0.0, < 2.0.0"}
# Pessimistic constraintmodule "vpc" { source = "localhost:8080/terraform/modules/vpc" version = "~> 1.0"}OpenTofu
Artifact Keeper works seamlessly with OpenTofu:
# Use same configuration filestofu inittofu plantofu applyVagrant
Endpoint
Vagrant operations use the /vagrant/{repo} endpoint:
http://localhost:8080/vagrant/{repo}Key: vagrant
Box Configuration
Add Box from Registry
# Add box from Artifact Keepervagrant box add mycompany/ubuntu \ --box-version 20.04 \ --provider virtualbox \ http://localhost:8080/vagrant/boxes/mycompany/ubuntu.jsonVagrantfile Configuration
Vagrant.configure("2") do |config| config.vm.box = "mycompany/ubuntu" config.vm.box_version = "20.04" config.vm.box_url = "http://localhost:8080/vagrant/boxes/mycompany/ubuntu.json"
config.vm.provider "virtualbox" do |vb| vb.memory = "2048" vb.cpus = 2 endendPublishing Boxes
Create Box Metadata
Create ubuntu.json:
{ "name": "mycompany/ubuntu", "description": "Ubuntu 20.04 LTS", "versions": [ { "version": "20.04", "providers": [ { "name": "virtualbox", "url": "http://localhost:8080/vagrant/boxes/mycompany/ubuntu/20.04/virtualbox.box", "checksum_type": "sha256", "checksum": "abc123..." } ] } ]}Upload Box
# Create box from existing VMvagrant package --output ubuntu-20.04.box
# Upload box filecurl -X PUT \ -H "Authorization: Bearer your-token" \ -F "file=@ubuntu-20.04.box" \ http://localhost:8080/vagrant/boxes/mycompany/ubuntu/20.04/virtualbox.box
# Upload metadatacurl -X PUT \ -H "Authorization: Bearer your-token" \ -H "Content-Type: application/json" \ -d @ubuntu.json \ http://localhost:8080/vagrant/boxes/mycompany/ubuntu.jsonDownloading Boxes
# List available boxesvagrant box list
# Update boxesvagrant box update
# Remove boxvagrant box remove mycompany/ubuntu --box-version 20.04Chef
Endpoint
Chef operations use the /chef/{repo} endpoint:
http://localhost:8080/chef/{repo}Key: chef
Clients
Compatible with:
knife- Chef command-line toolberkshelf- Cookbook dependency manager
Supermarket Configuration
Knife Configuration
Create or edit ~/.chef/config.rb:
current_dir = File.dirname(__FILE__)node_name "your-username"client_key "#{current_dir}/your-username.pem"chef_server_url "http://localhost:8080/chef/organizations/mycompany"cookbook_path ["#{current_dir}/../cookbooks"]
# Supermarket configurationknife[:supermarket_site] = 'http://localhost:8080/chef/supermarket'Berkshelf Configuration
Create or edit ~/.berkshelf/config.json:
{ "chef": { "chef_server_url": "http://localhost:8080/chef/organizations/mycompany", "node_name": "your-username", "client_key": "/path/to/your-username.pem" }, "ssl": { "verify": false }}Uploading Cookbooks
Cookbook Structure
my-cookbook/├── metadata.rb├── README.md├── recipes/│ └── default.rb├── attributes/│ └── default.rb├── templates/└── test/metadata.rb
name 'my-cookbook'maintainer 'Your Company'maintainer_email 'chef@example.com'license 'Apache-2.0'description 'Installs/Configures my-cookbook'version '1.0.0'
depends 'apt', '~> 7.0'depends 'nginx', '>= 8.0'Upload with Knife
# Upload single cookbookknife cookbook upload my-cookbook
# Upload cookbook with dependenciesknife cookbook upload my-cookbook --include-dependencies
# Upload all cookbooksknife cookbook upload --allUpload with Berkshelf
# Install dependenciesberks install
# Upload to Chef Serverberks uploadInstalling Cookbooks
With Knife
# Download cookbookknife cookbook download my-cookbook 1.0.0
# List cookbooksknife cookbook listWith Berkshelf
Create Berksfile:
source 'http://localhost:8080/chef/supermarket'
metadata
cookbook 'my-cookbook', '~> 1.0.0'cookbook 'nginx', '>= 8.0'Install:
berks installPuppet
Endpoint
Puppet operations use the /puppet/{repo} endpoint:
http://localhost:8080/puppet/{repo}Key: puppet
Clients
Compatible with:
puppet module- Puppet module management
Module Repository Configuration
puppet.conf
Add to puppet.conf:
[main]module_repository = http://localhost:8080/puppet/modulesCommand-Line Override
puppet module install mycompany-apache \ --module_repository=http://localhost:8080/puppet/modulesPublishing Modules
Module Structure
puppet-apache/├── metadata.json├── README.md├── manifests/│ └── init.pp├── files/├── templates/├── lib/└── spec/metadata.json
{ "name": "mycompany-apache", "version": "1.0.0", "author": "Your Company", "summary": "Apache HTTP Server module", "license": "Apache-2.0", "source": "https://github.com/mycompany/puppet-apache", "project_page": "https://github.com/mycompany/puppet-apache", "dependencies": [ { "name": "puppetlabs/stdlib", "version_requirement": ">= 4.0.0 < 9.0.0" } ], "operatingsystem_support": [ { "operatingsystem": "Ubuntu", "operatingsystemrelease": ["18.04", "20.04"] } ]}Build and Publish
# Build module packagepuppet module build
# This creates pkg/mycompany-apache-1.0.0.tar.gz
# Upload to registrycurl -X PUT \ -H "Authorization: Bearer your-token" \ -F "file=@pkg/mycompany-apache-1.0.0.tar.gz" \ http://localhost:8080/puppet/modules/mycompany-apache-1.0.0.tar.gzInstalling Modules
# Install latest versionpuppet module install mycompany-apache
# Install specific versionpuppet module install mycompany-apache --version 1.0.0
# Install with dependenciespuppet module install mycompany-apache --ignore-dependencies=falsePuppetfile
For r10k or Librarian-Puppet:
forge 'http://localhost:8080/puppet/modules'
mod 'mycompany-apache', '1.0.0'mod 'puppetlabs-stdlib', '>= 4.0.0'Ansible
Endpoint
Ansible operations use the /ansible/{repo} endpoint:
http://localhost:8080/ansible/{repo}Key: ansible
Clients
Compatible with:
ansible-galaxy- Ansible content manager
Galaxy Server Configuration
ansible.cfg
Create or edit ansible.cfg:
[galaxy]server_list = artifact_keeper
[galaxy_server.artifact_keeper]url=http://localhost:8080/ansible/galaxy/token=your-api-tokenEnvironment Variable
export ANSIBLE_GALAXY_SERVER_LIST=artifact_keeperexport ANSIBLE_GALAXY_SERVER_ARTIFACT_KEEPER_URL=http://localhost:8080/ansible/galaxy/export ANSIBLE_GALAXY_SERVER_ARTIFACT_KEEPER_TOKEN=your-api-tokenPublishing Collections
Collection Structure
my_namespace.my_collection/├── galaxy.yml├── README.md├── plugins/│ ├── modules/│ ├── inventory/│ └── filter/├── roles/│ └── my_role/└── docs/galaxy.yml
namespace: my_namespacename: my_collectionversion: 1.0.0readme: README.mdauthors: - Your Name <you@example.com>description: My awesome Ansible collectionlicense: - MITtags: - automation - infrastructuredependencies: ansible.posix: ">=1.0.0" community.general: ">=3.0.0"repository: https://github.com/mycompany/my_collectiondocumentation: https://docs.example.com/my_collectionhomepage: https://example.com/my_collectionissues: https://github.com/mycompany/my_collection/issuesBuild Collection
# Build collection tarballansible-galaxy collection build
# This creates my_namespace-my_collection-1.0.0.tar.gzPublish Collection
# Publish to Artifact Keeperansible-galaxy collection publish \ my_namespace-my_collection-1.0.0.tar.gz \ --server artifact_keeperPublishing Roles
Role Structure
my-role/├── meta/│ └── main.yml├── tasks/│ └── main.yml├── handlers/│ └── main.yml├── templates/├── files/├── vars/│ └── main.yml├── defaults/│ └── main.yml└── README.mdmeta/main.yml
galaxy_info: author: Your Name description: My awesome role company: Your Company license: MIT min_ansible_version: "2.9" platforms: - name: Ubuntu versions: - focal - jammy galaxy_tags: - web - nginx
dependencies: - role: geerlingguy.apache version: "3.0.0"Import Role
# Import from Gitansible-galaxy role import \ --server artifact_keeper \ github_user repo_nameInstalling Collections
# Install collectionansible-galaxy collection install my_namespace.my_collection
# Install specific versionansible-galaxy collection install my_namespace.my_collection:1.0.0
# Install from requirements fileansible-galaxy collection install -r requirements.ymlrequirements.yml
collections: - name: my_namespace.my_collection version: ">=1.0.0" source: http://localhost:8080/ansible/galaxy/
- name: ansible.posix version: "1.5.1"Installing Roles
# Install roleansible-galaxy role install my_namespace.my_role
# Install from requirementsansible-galaxy role install -r requirements.ymlrequirements.yml for Roles
roles: - name: my_namespace.my_role version: "1.0.0" src: http://localhost:8080/ansible/galaxy/
- name: geerlingguy.apache version: "3.0.0"CI/CD Integration
Terraform in GitHub Actions
name: Terraform Moduleon: push: tags: - 'v*'
jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Package module run: | tar -czf module.tar.gz -C module .
- name: Publish to Artifact Keeper run: | curl -X PUT \ -H "Authorization: Bearer ${{ secrets.TERRAFORM_TOKEN }}" \ -F "file=@module.tar.gz" \ http://registry.example.com/terraform/modules/mycompany/vpc/aws/${GITHUB_REF#refs/tags/v}Chef in GitLab CI
publish_cookbook: image: chef/chefworkstation:latest stage: deploy script: - knife cookbook upload my-cookbook --force only: - tagsAnsible in Jenkins
pipeline { agent any
stages { stage('Publish Collection') { steps { sh ''' ansible-galaxy collection build ansible-galaxy collection publish \ *.tar.gz \ --server artifact_keeper \ --token $ANSIBLE_GALAXY_TOKEN ''' } } }}Troubleshooting
Terraform Module Not Found
Verify module source format:
# List available modulescurl http://localhost:8080/terraform/modules/Check Terraform configuration:
terraform init -upgradeVagrant Box Download Fails
Check box URL in Vagrantfile:
# Test box metadatacurl http://localhost:8080/vagrant/boxes/mycompany/ubuntu.jsonVerify box exists:
vagrant box listChef Upload Authentication Error
Verify credentials:
knife client listTest connection:
knife ssl checkPuppet Module Installation Fails
Check module repository:
puppet module list --modulepath=/path/to/modulesClear module cache:
rm -rf ~/.puppet/var/puppet-module/cacheAnsible Collection Not Found
List configured servers:
ansible-galaxy collection listVerify server configuration:
ansible-galaxy collection list --server artifact_keeperClear cache:
rm -rf ~/.ansible/collectionsBest Practices
Version Management
Follow semantic versioning for all package types:
- Major (1.0.0 -> 2.0.0): Breaking changes
- Minor (1.0.0 -> 1.1.0): New features, backward compatible
- Patch (1.0.0 -> 1.0.1): Bug fixes
Documentation
Include comprehensive documentation:
- README.md with usage examples
- CHANGELOG.md with version history
- LICENSE file
- Examples directory with sample configurations
Testing
Test infrastructure code before publishing:
- Terraform:
terraform validate,terraform plan - Vagrant: Test box provisioning
- Chef:
kitchen test - Puppet:
puppet parser validate,pdk test unit - Ansible:
ansible-lint,molecule test
Metadata
Include complete metadata:
- Author and maintainer information
- Dependencies with version constraints
- Supported platforms and versions
- License information
- Source repository and documentation links
See Also
- Security Scanning - Automatic vulnerability scanning
- Security Policies - Configure policies to block vulnerable packages