#!/usr/bin/env nu # Create registry users with htpasswd export def main [ --registry-type: string = "distribution" # distribution, zot --output: string = "./htpasswd" ] { print "šŸ‘„ Creating registry users..." print $" Registry type: ($registry_type)" print $" Output file: ($output)\n" let users = get-default-users # Create or clear htpasswd file if ($output | path exists) { let confirm = (input "āš ļø htpasswd file exists. Overwrite? (y/N): ") if $confirm != "y" { print "Cancelled" return } rm $output } for user in $users { print $"Adding user: ($user.username) \(($user.role)\)" let password = if ($user.password | is-empty) { input $" Enter password for ($user.username): " } else { $user.password } # Create htpasswd entry create-htpasswd-entry $output $user.username $password print $" āœ“ User ($user.username) added" } print "\nāœ… Users created successfully!" print $"\nšŸ“‹ Next steps:" print $"1. Copy htpasswd file to registry:" print $" cp ($output) ($registry_type)/htpasswd" print "2. Restart registry service" print "3. Test login:" print " docker login localhost:5000" } def get-default-users [] -> list { [ { username: "provisioning" password: "" # Will prompt role: "admin" } { username: "developer" password: "" role: "developer" } { username: "readonly" password: "" role: "readonly" } ] } def create-htpasswd-entry [file: string, username: string, password: string] { # Use htpasswd if available, otherwise use openssl let htpasswd_available = (which htpasswd | length) > 0 if $htpasswd_available { # Use htpasswd (bcrypt) if ($file | path exists) { ^htpasswd -bB $file $username $password } else { ^htpasswd -cbB $file $username $password } } else { # Fallback to openssl (less secure but works) print " āš ļø htpasswd not found, using openssl (less secure)" let hash = (^openssl passwd -apr1 $password) let entry = $"($username):($hash)\n" if ($file | path exists) { $entry | save --append $file } else { $entry | save $file } } } # Add single user export def "user add" [ username: string --password: string --htpasswd-file: string = "./htpasswd" ] { print $"Adding user: ($username)" let pwd = if ($password | is-empty) { input $"Enter password for ($username): " } else { $password } create-htpasswd-entry $htpasswd_file $username $pwd print "āœ… User added" } # Remove user export def "user remove" [ username: string --htpasswd-file: string = "./htpasswd" ] { if not ($htpasswd_file | path exists) { error make {msg: $"htpasswd file not found: ($htpasswd_file)"} } print $"Removing user: ($username)" # Read file, filter out user, write back let entries = (open $htpasswd_file | lines | where { |line| not ($line | str starts-with $"($username):") }) $entries | str join "\n" | save -f $htpasswd_file print "āœ… User removed" } # List users export def "user list" [ --htpasswd-file: string = "./htpasswd" ] { if not ($htpasswd_file | path exists) { print "No htpasswd file found" return } print "Registry users:\n" open $htpasswd_file | lines | each { |line| let username = ($line | split row ":" | first) {username: $username} } } # Change password export def "user password" [ username: string --htpasswd-file: string = "./htpasswd" ] { if not ($htpasswd_file | path exists) { error make {msg: $"htpasswd file not found: ($htpasswd_file)"} } print $"Changing password for: ($username)" # Remove old entry user remove $username --htpasswd-file $htpasswd_file # Add new entry user add $username --htpasswd-file $htpasswd_file print "āœ… Password changed" }