Skip to main content
This homelab uses comin for GitOps-based automatic deployments. Systems automatically pull and apply configuration changes from the Git repository, enabling declarative infrastructure management.

How It Works

Comin is a NixOS service that:
  1. Monitors a Git repository for changes
  2. Pulls updates from specified branches
  3. Rebuilds the NixOS configuration
  4. Applies changes automatically
This creates a continuous deployment pipeline where pushing to Git triggers system updates.

Configuration

The GitOps functionality is provided by the core.gitops module:
# modules/nixos/core/gitops.nix
options.core.gitops = {
  enable = mkEnableOption "Enable gitops based update cycles on system";
  repo = mkOption {
    type = types.str;
    description = "The url to retrieve the flake configuration from";
    example = "https://github.com/soriphoono/homelab.git";
  };
  name = mkOption {
    type = types.str;
    description = "The name of the configuration to update from";
    example = "zephyrus";
  };
};

Enabling GitOps on a System

1

Enable the module in your system configuration

Add to your host’s configuration:
# systems/zephyrus/default.nix
{
  core.gitops = {
    enable = true;
    repo = "https://github.com/soriphoono/homelab.git";
    name = "zephyrus";
  };
}
2

Deploy the initial configuration

Apply the configuration manually the first time:
nixos-rebuild switch --flake .#zephyrus
3

Verify comin is running

Check the service status:
systemctl status comin
You should see the service is active and monitoring the repository.
4

Test automatic deployment

Make a change to your configuration and push to Git:
git add .
git commit -m "Test GitOps deployment"
git push
Comin will detect the change and rebuild the system automatically.

Comin Service Configuration

The module translates options into comin’s service configuration:
services.comin = {
  enable = true;
  hostname = cfg.name;
  remotes = [
    {
      name = "origin";
      url = cfg.repo;
      branches.main.name = "main";
    }
  ];
};

Key Parameters

  • hostname: Matches the flake output name (e.g., nixosConfigurations.zephyrus)
  • remotes: Git repositories to monitor
  • branches.main.name: Which branch to track (typically main or master)

GitOps Workflow

Development Workflow

  1. Make changes in a development environment
  2. Test locally with nixos-rebuild test
  3. Commit and push to a feature branch
  4. Test on a non-production system
  5. Merge to main branch
  6. Production systems automatically deploy

Rollback Procedure

If a deployment causes issues:
1

Revert the Git commit

git revert HEAD
git push
Comin will automatically deploy the reverted configuration.
2

Or use NixOS generations (immediate rollback)

nixos-rebuild switch --rollback
This immediately switches to the previous generation without waiting for comin.

Branch Strategy

Single Branch (Simple)

  • All systems track main
  • Changes deploy to all systems simultaneously
  • Best for homelab environments
branches.main.name = "main";

Multi-Branch (Advanced)

  • Development systems track develop
  • Production systems track main
  • Allows staged rollouts
remotes = [
  {
    name = "origin";
    url = cfg.repo;
    branches.main.name = "develop"; # For dev systems
  }
];

Monitoring Deployments

Check comin logs

journalctl -u comin -f
This shows real-time updates as comin pulls and deploys changes.

View deployment history

nixos-rebuild list-generations
Shows all system generations with timestamps and activation dates.

Security Considerations

  • Use HTTPS or SSH URLs for private repositories
  • Consider authentication for private repos (deploy keys, tokens)
  • Monitor comin logs for unauthorized changes
  • Test critical changes in a staging environment first

Authentication for Private Repositories

Using Deploy Keys

  1. Generate an SSH key on the system:
    ssh-keygen -t ed25519 -f /root/.ssh/comin_deploy_key
    
  2. Add the public key as a deploy key in GitHub/GitLab
  3. Configure comin to use the key:
    remotes = [
      {
        name = "origin";
        url = "[email protected]:soriphoono/homelab.git";
        branches.main.name = "main";
      }
    ];
    

Using GitHub Tokens

For HTTPS repositories, embed a token in the URL:
url = "https://oauth2:${token}@github.com/soriphoono/homelab.git";
Store the token using agenix for security.

Disabling GitOps Temporarily

To stop automatic deployments without removing the configuration:
systemctl stop comin
systemctl disable comin
Re-enable with:
systemctl enable --now comin

Troubleshooting

Comin not pulling changes

Check the repository URL and branch configuration:
journalctl -u comin | grep -i error

Build failures

Comin will retry automatically. Check the logs:
journalctl -u comin --since "1 hour ago"
Fix the issue in Git and push a new commit.

Authentication failures

Verify SSH keys or tokens are correctly configured:
# Test SSH access
sudo -u root ssh -T [email protected]

# Check comin user permissions
systemctl cat comin | grep User

Best Practices

  • Use atomic commits (one logical change per commit)
  • Write descriptive commit messages
  • Test changes locally before pushing
  • Monitor the first deployment after enabling GitOps
  • Keep secrets in agenix, not in the Git history
  • Use pull requests for critical infrastructure changes

Build docs developers (and LLMs) love