package main import ( "fmt" "log" "path/filepath" "strconv" "sync" "time" "git.nevets.tech/Steven/ezconf" "github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-git/v5/storage/memory" ) var ( tickMu sync.Mutex mgr *ACMEManager mgrMu sync.Mutex ) func getACMEManager() (*ACMEManager, error) { mgrMu.Lock() defer mgrMu.Unlock() if mgr == nil { var err error mgr, err = NewACMEManager() if err != nil { return nil, err } } return mgr, nil } func initServer() { err := loadDomainConfigs() if err != nil { log.Fatalf("Error loading domain configs: %v", err) } } func serverTick() { tickMu.Lock() defer tickMu.Unlock() fmt.Println("Tick!") mgr, err := getACMEManager() if err != nil { fmt.Printf("Error getting acme manager: %v\n", err) return } now := time.Now().UTC() mu.RLock() localDomainConfigs := make(map[string]*ezconf.Configuration, len(domainConfigs)) for k, v := range domainConfigs { localDomainConfigs[k] = v } mu.RUnlock() for domainStr, domainConfig := range localDomainConfigs { if !domainConfig.GetAsBoolean("Domain.enabled") { continue } renewPeriod := domainConfig.GetAsInt("Certificates.renew_period") lastIssued := time.Unix(domainConfig.GetAsInt64("Internal.last_issued"), 0).UTC() renewalDue := lastIssued.AddDate(0, 0, renewPeriod) if now.After(renewalDue) { _, err = mgr.RenewForDomain(domainStr) if err != nil { // if no existing cert, obtain instead _, err = mgr.ObtainForDomain(domainStr) if err != nil { fmt.Printf("Error obtaining domain certificates for domain %s: %v\n", domainStr, err) continue } } err = domainConfig.SetValueErr("Internal.last_issued", strconv.FormatInt(time.Now().UTC().Unix(), 10)) if err != nil { fmt.Printf("Error updating last_issued config for domain %s: %v\n", domainStr, err) continue } err = domainConfig.Save() if err != nil { fmt.Printf("Error saving domain config %s: %v\n", domainStr, err) continue } err = EncryptFileXChaCha(domainConfig.GetAsString("Certificates.crypto_key"), filepath.Join(mgr.certsRoot, domainStr, domainStr+".crt"), filepath.Join(mgr.certsRoot, domainStr, domainStr+".crt.crpt"), nil) if err != nil { fmt.Printf("Error encrypting domain cert for domain %s: %v\n", domainStr, err) continue } err = EncryptFileXChaCha(domainConfig.GetAsString("Certificates.crypto_key"), filepath.Join(mgr.certsRoot, domainStr, domainStr+".key"), filepath.Join(mgr.certsRoot, domainStr, domainStr+".key.crpt"), nil) if err != nil { fmt.Printf("Error encrypting domain key for domain %s: %v\n", domainStr, err) continue } giteaClient := createGiteaClient() if giteaClient == nil { fmt.Printf("Error creating gitea client for domain %s: %v\n", domainStr, err) continue } gitWorkspace := &GitWorkspace{ Storage: memory.NewStorage(), FS: memfs.New(), } var repoUrl string if !domainConfig.GetAsBoolean("Internal.repo_exists") { repoUrl = createGiteaRepo(domainStr, giteaClient) if repoUrl == "" { fmt.Printf("Error creating Gitea repo for domain %s\n", domainStr) continue } err = domainConfig.SetValueErr("Internal.repo_exists", "true") if err != nil { fmt.Printf("Error updating repo_exists config for domain %s: %v\n", domainStr, err) continue } err = domainConfig.Save() if err != nil { fmt.Printf("Error saving domain config %s: %v\n", domainStr, err) continue } err = initRepo(repoUrl, gitWorkspace) if err != nil { fmt.Printf("Error initializing repo for domain %s: %v\n", domainStr, err) continue } } else { repoUrl = config.GetAsString("Git.server") + "/" + config.GetAsString("Git.org_name") + "/" + domainStr + domainConfig.GetAsString("Repo.repo_suffix") + ".git" err = cloneRepo(repoUrl, gitWorkspace) if err != nil { fmt.Printf("Error cloning repo for domain %s: %v\n", domainStr, err) continue } } err = addAndPushCerts(domainStr, gitWorkspace) if err != nil { fmt.Printf("Error pushing certificates for domain %s: %v\n", domainStr, err) continue } fmt.Printf("Successfully pushed certificates for domain %s\n", domainStr) } } saveDomainConfigs() } func reloadServer() { fmt.Println("Reloading configs...") err := loadDomainConfigs() if err != nil { fmt.Printf("Error loading domain configs: %v\n", err) return } mgrMu.Lock() mgr = nil mgrMu.Unlock() fmt.Println("Successfully reloaded configs") } func stopServer() { fmt.Println("Shutting down server") }