{"id":22976174,"url":"https://github.com/kintsdev/certy","last_synced_at":"2025-09-14T23:12:23.560Z","repository":{"id":244647321,"uuid":"812668314","full_name":"kintsdev/certy","owner":"kintsdev","description":"Certy is a Go package that automates the process of obtaining SSL certificates.","archived":false,"fork":false,"pushed_at":"2025-08-19T11:39:26.000Z","size":92,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-19T13:18:16.147Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kintsdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-06-09T14:47:44.000Z","updated_at":"2025-08-19T11:07:09.000Z","dependencies_parsed_at":"2024-11-08T00:24:26.630Z","dependency_job_id":"884dead6-f69f-4ff3-8cd4-a6a019c22af1","html_url":"https://github.com/kintsdev/certy","commit_stats":null,"previous_names":["kintsdev/certy"],"tags_count":38,"template":false,"template_full_name":null,"purl":"pkg:github/kintsdev/certy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kintsdev%2Fcerty","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kintsdev%2Fcerty/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kintsdev%2Fcerty/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kintsdev%2Fcerty/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kintsdev","download_url":"https://codeload.github.com/kintsdev/certy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kintsdev%2Fcerty/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275180222,"owners_count":25419066,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-15T00:48:21.895Z","updated_at":"2025-09-14T23:12:23.534Z","avatar_url":"https://github.com/kintsdev.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"logo.png\" alt=\"Certy\" width=\"200\" height=\"200\"\u003e\n\u003c/p\u003e\n\n\n# Certy - Let's Encrypt Certificate Manager\n\nCerty is a Go library for managing Let's Encrypt SSL/TLS certificates with automatic renewal and custom certificate support.\n\n## Features\n\n- **Automatic Let's Encrypt Certificate Management**: Issue and renew SSL certificates automatically\n- **HTTP-01 Challenge Support**: Built-in ACME challenge handler for domain verification\n- **Custom Certificate Support**: Add your own certificates alongside Let's Encrypt ones\n- **Thread-Safe Operations**: Concurrent certificate issuance with proper locking\n- **Automatic Renewal**: Certificates are renewed 30 days before expiry\n- **Staging Environment Support**: Test with Let's Encrypt staging servers first\n\n## Installation\n\n```bash\ngo get github.com/kintsdev/certy\n```\n\n## Quick Start\n\n### Basic Usage\n\n```go\npackage main\n\nimport (\n    \"log\"\n    \"github.com/kintsdev/certy\"\n)\n\nfunc main() {\n    // Create a new certificate manager\n    manager := certy.NewManager(\n        \"your-email@example.com\", // Your email for Let's Encrypt\n        \"./certs\",                // Directory to store certificates\n        true,                     // Use staging environment first\n    )\n\n    // Issue a certificate for a domain\n    err := manager.IssueCert(\"example.com\")\n    if err != nil {\n        log.Fatalf(\"Failed to issue certificate: %v\", err)\n    }\n}\n```\n\n### HTTP Server with Automatic Certificates\n\n```go\npackage main\n\nimport (\n    \"crypto/tls\"\n    \"fmt\"\n    \"log\"\n    \"net/http\"\n    \"github.com/kintsdev/certy\"\n)\n\nfunc main() {\n    manager := certy.NewManager(\"your-email@example.com\", \"./certs\", false)\n    \n    // Create server with automatic certificate management\n    server := \u0026http.Server{\n        Addr: \":8443\",\n        TLSConfig: \u0026tls.Config{\n            GetCertificate: manager.GetCert, // Automatically selects certificates\n        },\n        Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n            fmt.Fprintf(w, \"Hello from %s!\", r.Host)\n        }),\n    }\n\n    // Wrap with ACME challenge handler for Let's Encrypt verification\n    handler := manager.HTTPHandler(server.Handler)\n    server.Handler = handler\n\n    log.Fatal(server.ListenAndServeTLS(\"\", \"\"))\n}\n```\n\n### Adding Custom Certificates\n\n```go\n// Add a custom certificate\nerr := manager.AddCustomCert(\n    \"custom.example.com\",\n    certPEMData,\n    keyPEMData,\n)\nif err != nil {\n    log.Printf(\"Failed to add custom certificate: %v\", err)\n}\n```\n\n## API Reference\n\n### Manager\n\nThe main struct for managing certificates.\n\n```go\ntype Manager struct {\n    Email    string // Email for Let's Encrypt account\n    Location string // Directory to store certificates\n    Staging  bool   // Use staging environment\n}\n```\n\n#### Methods\n\n- `NewManager(email, location string, staging bool) *Manager` - Create a new manager\n- `IssueCert(domain string) error` - Issue a Let's Encrypt certificate\n- `AddCustomCert(domain, certData, keyData string) error` - Add a custom certificate\n- `GetCert(hello *tls.ClientHelloInfo) (*tls.Certificate, error)` - Get TLS certificate for domain\n- `HTTPHandler(fallback http.Handler) http.Handler` - ACME challenge handler\n- `GetAcmeFileData(domain string) (*DomainAcme, error)` - Get ACME data for domain\n- `GetChallengeToken(domain string) (string, error)` - Get challenge token for domain\n\n### DomainAcme\n\nRepresents certificate data for a domain.\n\n```go\ntype DomainAcme struct {\n    Sans       []string        // Subject Alternative Names\n    IssuerData IssuerData      // Let's Encrypt issuer information\n    AccountKey *rsa.PrivateKey // Account private key\n    CertFile   string          // Certificate file path\n    KeyFile    string          // Private key file path\n    ExpireDate time.Time       // Certificate expiry date\n    IssueDate  time.Time       // Certificate issue date\n    CustomCert bool            // Whether this is a custom certificate\n}\n```\n\n#### Methods\n\n- `RenewRequired() bool` - Check if renewal is needed (30 days before expiry)\n- `Expired() bool` - Check if certificate is expired\n- `IsNull() bool` - Check if ACME data is empty\n\n## File Structure\n\nCerty creates the following directory structure:\n\n```\ncerts/\n├── example.com/\n│   ├── example.com-acme.json    # ACME data and metadata\n│   ├── example.com-cert.crt     # Certificate chain\n│   └── example.com-key.pem      # Private key\n└── another-domain.com/\n    ├── another-domain.com-acme.json\n    ├── another-domain.com-cert.crt\n    └── another-domain.com-key.pem\n```\n\n## Configuration\n\n### Environment Variables\n\n- `CERTY_EMAIL`: Your email for Let's Encrypt (optional, can be set in code)\n- `CERTY_LOCATION`: Certificate storage directory (optional, can be set in code)\n- `CERTY_STAGING`: Use staging environment (optional, defaults to false)\n\n### Let's Encrypt Rate Limits\n\n- **Staging**: 300 new orders per 3 hours, 300 new registrations per 1 hour\n- **Production**: 300 new orders per 3 hours, 300 new registrations per 3 hours\n\nAlways test with staging first!\n\n## Security Considerations\n\n- Private keys are stored with 0644 permissions (readable by owner only)\n- Directories are created with 0755 permissions\n- Account keys are RSA 4096-bit\n- Certificate keys are ECDSA P-256\n- Certificates expire after 88 days (renewed 30 days before expiry)\n\n## Error Handling\n\nAll methods return proper errors that should be checked:\n\n```go\nerr := manager.IssueCert(\"example.com\")\nif err != nil {\n    switch {\n    case strings.Contains(err.Error(), \"already in progress\"):\n        log.Println(\"Certificate issuance already in progress\")\n    case strings.Contains(err.Error(), \"challenge failed\"):\n        log.Println(\"Domain verification failed\")\n    default:\n        log.Printf(\"Unexpected error: %v\", err)\n    }\n}\n```\n\n## Testing\n\nRun the test suite:\n\n```bash\ngo test ./...\n```\n\n## Examples\n\nSee the `example/` directory for complete working examples.\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests for new functionality\n5. Ensure all tests pass\n6. Submit a pull request\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Recent Fixes\n\nThis version includes several important fixes:\n\n- **Proper error handling**: All errors are now properly returned and handled\n- **Thread safety**: Added mutex protection for concurrent operations\n- **File path security**: Using `filepath.Join` for secure path construction\n- **Resource cleanup**: Proper file handle management and cleanup\n- **Logic fixes**: Corrected certificate renewal logic and validation\n- **Code organization**: Split large functions into smaller, testable functions\n- **Input validation**: Added proper validation for all inputs\n- **Documentation**: Comprehensive comments and examples\n\n## Support\n\nFor issues and questions, please open an issue on GitHub.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkintsdev%2Fcerty","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkintsdev%2Fcerty","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkintsdev%2Fcerty/lists"}