at 25.11-pre 30 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.services.athens; 9 10 athensConfig = lib.flip lib.recursiveUpdate cfg.extraConfig ({ 11 GoBinary = "${cfg.goBinary}/bin/go"; 12 GoEnv = cfg.goEnv; 13 GoBinaryEnvVars = lib.mapAttrsToList (k: v: "${k}=${v}") cfg.goBinaryEnvVars; 14 GoGetWorkers = cfg.goGetWorkers; 15 GoGetDir = cfg.goGetDir; 16 ProtocolWorkers = cfg.protocolWorkers; 17 LogLevel = cfg.logLevel; 18 CloudRuntime = cfg.cloudRuntime; 19 EnablePprof = cfg.enablePprof; 20 PprofPort = ":${toString cfg.pprofPort}"; 21 FilterFile = cfg.filterFile; 22 RobotsFile = cfg.robotsFile; 23 Timeout = cfg.timeout; 24 StorageType = cfg.storageType; 25 TLSCertFile = cfg.tlsCertFile; 26 TLSKeyFile = cfg.tlsKeyFile; 27 Port = ":${toString cfg.port}"; 28 UnixSocket = cfg.unixSocket; 29 GlobalEndpoint = cfg.globalEndpoint; 30 BasicAuthUser = cfg.basicAuthUser; 31 BasicAuthPass = cfg.basicAuthPass; 32 ForceSSL = cfg.forceSSL; 33 ValidatorHook = cfg.validatorHook; 34 PathPrefix = cfg.pathPrefix; 35 NETRCPath = cfg.netrcPath; 36 GithubToken = cfg.githubToken; 37 HGRCPath = cfg.hgrcPath; 38 TraceExporter = cfg.traceExporter; 39 StatsExporter = cfg.statsExporter; 40 SumDBs = cfg.sumDBs; 41 NoSumPatterns = cfg.noSumPatterns; 42 DownloadMode = cfg.downloadMode; 43 NetworkMode = cfg.networkMode; 44 DownloadURL = cfg.downloadURL; 45 SingleFlightType = cfg.singleFlightType; 46 IndexType = cfg.indexType; 47 ShutdownTimeout = cfg.shutdownTimeout; 48 SingleFlight = { 49 Etcd = { 50 Endpoints = builtins.concatStringsSep "," cfg.singleFlight.etcd.endpoints; 51 }; 52 Redis = { 53 Endpoint = cfg.singleFlight.redis.endpoint; 54 Password = cfg.singleFlight.redis.password; 55 LockConfig = { 56 TTL = cfg.singleFlight.redis.lockConfig.ttl; 57 Timeout = cfg.singleFlight.redis.lockConfig.timeout; 58 MaxRetries = cfg.singleFlight.redis.lockConfig.maxRetries; 59 }; 60 }; 61 RedisSentinel = { 62 Endpoints = cfg.singleFlight.redisSentinel.endpoints; 63 MasterName = cfg.singleFlight.redisSentinel.masterName; 64 SentinelPassword = cfg.singleFlight.redisSentinel.sentinelPassword; 65 LockConfig = { 66 TTL = cfg.singleFlight.redisSentinel.lockConfig.ttl; 67 Timeout = cfg.singleFlight.redisSentinel.lockConfig.timeout; 68 MaxRetries = cfg.singleFlight.redisSentinel.lockConfig.maxRetries; 69 }; 70 }; 71 }; 72 Storage = { 73 CDN = { 74 Endpoint = cfg.storage.cdn.endpoint; 75 }; 76 Disk = { 77 RootPath = cfg.storage.disk.rootPath; 78 }; 79 GCP = { 80 ProjectID = cfg.storage.gcp.projectID; 81 Bucket = cfg.storage.gcp.bucket; 82 JSONKey = cfg.storage.gcp.jsonKey; 83 }; 84 Minio = { 85 Endpoint = cfg.storage.minio.endpoint; 86 Key = cfg.storage.minio.key; 87 Secret = cfg.storage.minio.secret; 88 EnableSSL = cfg.storage.minio.enableSSL; 89 Bucket = cfg.storage.minio.bucket; 90 region = cfg.storage.minio.region; 91 }; 92 Mongo = { 93 URL = cfg.storage.mongo.url; 94 DefaultDBName = cfg.storage.mongo.defaultDBName; 95 CertPath = cfg.storage.mongo.certPath; 96 Insecure = cfg.storage.mongo.insecure; 97 }; 98 S3 = { 99 Region = cfg.storage.s3.region; 100 Key = cfg.storage.s3.key; 101 Secret = cfg.storage.s3.secret; 102 Token = cfg.storage.s3.token; 103 Bucket = cfg.storage.s3.bucket; 104 ForcePathStyle = cfg.storage.s3.forcePathStyle; 105 UseDefaultConfiguration = cfg.storage.s3.useDefaultConfiguration; 106 CredentialsEndpoint = cfg.storage.s3.credentialsEndpoint; 107 AwsContainerCredentialsRelativeURI = cfg.storage.s3.awsContainerCredentialsRelativeURI; 108 Endpoint = cfg.storage.s3.endpoint; 109 }; 110 AzureBlob = { 111 AccountName = cfg.storage.azureblob.accountName; 112 AccountKey = cfg.storage.azureblob.accountKey; 113 ContainerName = cfg.storage.azureblob.containerName; 114 }; 115 External = { 116 URL = cfg.storage.external.url; 117 }; 118 }; 119 Index = { 120 MySQL = { 121 Protocol = cfg.index.mysql.protocol; 122 Host = cfg.index.mysql.host; 123 Port = cfg.index.mysql.port; 124 User = cfg.index.mysql.user; 125 Password = cfg.index.mysql.password; 126 Database = cfg.index.mysql.database; 127 Params = { 128 parseTime = cfg.index.mysql.params.parseTime; 129 timeout = cfg.index.mysql.params.timeout; 130 }; 131 }; 132 Postgres = { 133 Host = cfg.index.postgres.host; 134 Port = cfg.index.postgres.port; 135 User = cfg.index.postgres.user; 136 Password = cfg.index.postgres.password; 137 Database = cfg.index.postgres.database; 138 Params = { 139 connect_timeout = cfg.index.postgres.params.connect_timeout; 140 sslmode = cfg.index.postgres.params.sslmode; 141 }; 142 }; 143 }; 144 }); 145 146 configFile = lib.pipe athensConfig [ 147 (lib.filterAttrsRecursive (_k: v: v != null)) 148 ((pkgs.formats.toml { }).generate "config.toml") 149 ]; 150in 151{ 152 meta = { 153 maintainers = pkgs.athens.meta.maintainers; 154 doc = ./athens.md; 155 }; 156 157 options.services.athens = { 158 enable = lib.mkEnableOption "Go module datastore and proxy"; 159 160 package = lib.mkOption { 161 default = pkgs.athens; 162 defaultText = lib.literalExpression "pkgs.athens"; 163 example = "pkgs.athens"; 164 description = "Which athens derivation to use"; 165 type = lib.types.package; 166 }; 167 168 goBinary = lib.mkOption { 169 type = lib.types.package; 170 default = pkgs.go; 171 defaultText = lib.literalExpression "pkgs.go"; 172 example = "pkgs.go_1_23"; 173 description = '' 174 The Go package used by Athens at runtime. 175 176 Athens primarily runs two Go commands: 177 1. `go mod download -json <module>@<version>` 178 2. `go list -m -json <module>@latest` 179 ''; 180 }; 181 182 goEnv = lib.mkOption { 183 type = lib.types.enum [ 184 "development" 185 "production" 186 ]; 187 description = "Specifies the type of environment to run. One of 'development' or 'production'."; 188 default = "development"; 189 example = "production"; 190 }; 191 192 goBinaryEnvVars = lib.mkOption { 193 type = lib.types.attrs; 194 description = "Environment variables to pass to the Go binary."; 195 example = '' 196 { "GOPROXY" = "direct", "GODEBUG" = "true" } 197 ''; 198 default = { }; 199 }; 200 201 goGetWorkers = lib.mkOption { 202 type = lib.types.int; 203 description = "Number of workers concurrently downloading modules."; 204 default = 10; 205 example = 32; 206 }; 207 208 goGetDir = lib.mkOption { 209 type = lib.types.nullOr lib.types.path; 210 description = '' 211 Temporary directory that Athens will use to 212 fetch modules from VCS prior to persisting 213 them to a storage backend. 214 215 If the value is empty, Athens will use the 216 default OS temp directory. 217 ''; 218 default = null; 219 example = "/tmp/athens"; 220 }; 221 222 protocolWorkers = lib.mkOption { 223 type = lib.types.int; 224 description = "Number of workers concurrently serving protocol paths."; 225 default = 30; 226 }; 227 228 logLevel = lib.mkOption { 229 type = lib.types.nullOr ( 230 lib.types.enum [ 231 "panic" 232 "fatal" 233 "error" 234 "warning" 235 "info" 236 "debug" 237 "trace" 238 ] 239 ); 240 description = '' 241 Log level for Athens. 242 Supports all logrus log levels (https://github.com/Sirupsen/logrus#level-logging)". 243 ''; 244 default = "warning"; 245 example = "debug"; 246 }; 247 248 cloudRuntime = lib.mkOption { 249 type = lib.types.enum [ 250 "GCP" 251 "none" 252 ]; 253 description = '' 254 Specifies the Cloud Provider on which the Proxy/registry is running. 255 ''; 256 default = "none"; 257 example = "GCP"; 258 }; 259 260 enablePprof = lib.mkOption { 261 type = lib.types.bool; 262 description = "Enable pprof endpoints."; 263 default = false; 264 }; 265 266 pprofPort = lib.mkOption { 267 type = lib.types.port; 268 description = "Port number for pprof endpoints."; 269 default = 3301; 270 example = 443; 271 }; 272 273 filterFile = lib.mkOption { 274 type = lib.types.nullOr lib.types.path; 275 description = ''Filename for the include exclude filter.''; 276 default = null; 277 example = lib.literalExpression '' 278 pkgs.writeText "filterFile" ''' 279 - github.com/azure 280 + github.com/azure/azure-sdk-for-go 281 D golang.org/x/tools 282 ''' 283 ''; 284 }; 285 286 robotsFile = lib.mkOption { 287 type = lib.types.nullOr lib.types.path; 288 description = ''Provides /robots.txt for net crawlers.''; 289 default = null; 290 example = lib.literalExpression ''pkgs.writeText "robots.txt" "# my custom robots.txt ..."''; 291 }; 292 293 timeout = lib.mkOption { 294 type = lib.types.int; 295 description = "Timeout for external network calls in seconds."; 296 default = 300; 297 example = 3; 298 }; 299 300 storageType = lib.mkOption { 301 type = lib.types.enum [ 302 "memory" 303 "disk" 304 "mongo" 305 "gcp" 306 "minio" 307 "s3" 308 "azureblob" 309 "external" 310 ]; 311 description = "Specifies the type of storage backend to use."; 312 default = "disk"; 313 }; 314 315 tlsCertFile = lib.mkOption { 316 type = lib.types.nullOr lib.types.path; 317 description = "Path to the TLS certificate file."; 318 default = null; 319 example = "/etc/ssl/certs/athens.crt"; 320 }; 321 322 tlsKeyFile = lib.mkOption { 323 type = lib.types.nullOr lib.types.path; 324 description = "Path to the TLS key file."; 325 default = null; 326 example = "/etc/ssl/certs/athens.key"; 327 }; 328 329 port = lib.mkOption { 330 type = lib.types.port; 331 default = 3000; 332 description = '' 333 Port number Athens listens on. 334 ''; 335 example = 443; 336 }; 337 338 unixSocket = lib.mkOption { 339 type = lib.types.nullOr lib.types.path; 340 description = '' 341 Path to the unix socket file. 342 If set, Athens will listen on the unix socket instead of TCP socket. 343 ''; 344 default = null; 345 example = "/run/athens.sock"; 346 }; 347 348 globalEndpoint = lib.mkOption { 349 type = lib.types.str; 350 description = '' 351 Endpoint for a package registry in case of a proxy cache miss. 352 ''; 353 default = ""; 354 example = "http://upstream-athens.example.com:3000"; 355 }; 356 357 basicAuthUser = lib.mkOption { 358 type = lib.types.nullOr lib.types.str; 359 description = '' 360 Username for basic auth. 361 ''; 362 default = null; 363 example = "user"; 364 }; 365 366 basicAuthPass = lib.mkOption { 367 type = lib.types.nullOr lib.types.str; 368 description = '' 369 Password for basic auth. Warning: this is stored in plain text in the config file. 370 ''; 371 default = null; 372 example = "swordfish"; 373 }; 374 375 forceSSL = lib.mkOption { 376 type = lib.types.bool; 377 description = '' 378 Force SSL redirects for incoming requests. 379 ''; 380 default = false; 381 }; 382 383 validatorHook = lib.mkOption { 384 type = lib.types.nullOr lib.types.str; 385 description = '' 386 Endpoint to validate modules against. 387 388 Not used if empty. 389 ''; 390 default = null; 391 example = "https://validation.example.com"; 392 }; 393 394 pathPrefix = lib.mkOption { 395 type = lib.types.nullOr lib.types.str; 396 description = '' 397 Sets basepath for all routes. 398 ''; 399 default = null; 400 example = "/athens"; 401 }; 402 403 netrcPath = lib.mkOption { 404 type = lib.types.nullOr lib.types.path; 405 description = '' 406 Path to the .netrc file. 407 ''; 408 default = null; 409 example = "/home/user/.netrc"; 410 }; 411 412 githubToken = lib.mkOption { 413 type = lib.types.nullOr lib.types.str; 414 description = '' 415 Creates .netrc file with the given token to be used for GitHub. 416 Warning: this is stored in plain text in the config file. 417 ''; 418 default = null; 419 example = "ghp_1234567890"; 420 }; 421 422 hgrcPath = lib.mkOption { 423 type = lib.types.nullOr lib.types.path; 424 description = '' 425 Path to the .hgrc file. 426 ''; 427 default = null; 428 example = "/home/user/.hgrc"; 429 }; 430 431 traceExporter = lib.mkOption { 432 type = lib.types.nullOr ( 433 lib.types.enum [ 434 "jaeger" 435 "datadog" 436 ] 437 ); 438 description = '' 439 Trace exporter to use. 440 ''; 441 default = null; 442 }; 443 444 traceExporterURL = lib.mkOption { 445 type = lib.types.nullOr lib.types.str; 446 description = '' 447 URL endpoint that traces will be sent to. 448 ''; 449 default = null; 450 example = "http://localhost:14268"; 451 }; 452 453 statsExporter = lib.mkOption { 454 type = lib.types.nullOr (lib.types.enum [ "prometheus" ]); 455 description = "Stats exporter to use."; 456 default = null; 457 }; 458 459 sumDBs = lib.mkOption { 460 type = lib.types.listOf lib.types.str; 461 description = '' 462 List of fully qualified URLs that Athens will proxy 463 that the go command can use a checksum verifier. 464 ''; 465 default = [ "https://sum.golang.org" ]; 466 }; 467 468 noSumPatterns = lib.mkOption { 469 type = lib.types.listOf lib.types.str; 470 description = '' 471 List of patterns that Athens sum db proxy will return a 403 for. 472 ''; 473 default = [ ]; 474 example = [ "github.com/mycompany/*" ]; 475 }; 476 477 downloadMode = lib.mkOption { 478 type = lib.types.oneOf [ 479 (lib.types.enum [ 480 "sync" 481 "async" 482 "redirect" 483 "async_redirect" 484 "none" 485 ]) 486 (lib.types.strMatching "^file:.*$|^custom:.*$") 487 ]; 488 description = '' 489 Defines how Athens behaves when a module@version 490 is not found in storage. There are 7 options: 491 1. "sync": download the module synchronously and 492 return the results to the client. 493 2. "async": return 404, but asynchronously store the module 494 in the storage backend. 495 3. "redirect": return a 301 redirect status to the client 496 with the base URL as the DownloadRedirectURL from below. 497 4. "async_redirect": same as option number 3 but it will 498 asynchronously store the module to the backend. 499 5. "none": return 404 if a module is not found and do nothing. 500 6. "file:<path>": will point to an HCL file that specifies 501 any of the 5 options above based on different import paths. 502 7. "custom:<base64-encoded-hcl>" is the same as option 6 503 but the file is fully encoded in the option. This is 504 useful for using an environment variable in serverless 505 deployments. 506 ''; 507 default = "async_redirect"; 508 }; 509 510 networkMode = lib.mkOption { 511 type = lib.types.enum [ 512 "strict" 513 "offline" 514 "fallback" 515 ]; 516 description = '' 517 Configures how Athens will return the results 518 of the /list endpoint as it can be assembled from both its own 519 storage and the upstream VCS. 520 521 Note, that for better error messaging, this would also affect how other 522 endpoints behave. 523 524 Modes: 525 1. strict: merge VCS versions with storage versions, but fail if either of them fails. 526 2. offline: only get storage versions, never reach out to VCS. 527 3. fallback: only return storage versions, if VCS fails. Note this means that you may 528 see inconsistent results since fallback mode does a best effort of giving you what's 529 available at the time of requesting versions. 530 ''; 531 default = "strict"; 532 }; 533 534 downloadURL = lib.mkOption { 535 type = lib.types.str; 536 description = "URL used if DownloadMode is set to redirect."; 537 default = "https://proxy.golang.org"; 538 }; 539 540 singleFlightType = lib.mkOption { 541 type = lib.types.enum [ 542 "memory" 543 "etcd" 544 "redis" 545 "redis-sentinel" 546 "gcp" 547 "azureblob" 548 ]; 549 description = '' 550 Determines what mechanism Athens uses to manage concurrency flowing into the Athens backend. 551 ''; 552 default = "memory"; 553 }; 554 555 indexType = lib.mkOption { 556 type = lib.types.enum [ 557 "none" 558 "memory" 559 "mysql" 560 "postgres" 561 ]; 562 description = '' 563 Type of index backend Athens will use. 564 ''; 565 default = "none"; 566 }; 567 568 shutdownTimeout = lib.mkOption { 569 type = lib.types.int; 570 description = '' 571 Number of seconds to wait for the server to shutdown gracefully. 572 ''; 573 default = 60; 574 example = 1; 575 }; 576 577 singleFlight = { 578 etcd = { 579 endpoints = lib.mkOption { 580 type = lib.types.listOf lib.types.str; 581 description = "URLs that determine all distributed etcd servers."; 582 default = [ ]; 583 example = [ "localhost:2379" ]; 584 }; 585 }; 586 redis = { 587 endpoint = lib.mkOption { 588 type = lib.types.str; 589 description = "URL of the redis server."; 590 default = ""; 591 example = "localhost:6379"; 592 }; 593 password = lib.mkOption { 594 type = lib.types.str; 595 description = "Password for the redis server. Warning: this is stored in plain text in the config file."; 596 default = ""; 597 example = "swordfish"; 598 }; 599 600 lockConfig = { 601 ttl = lib.mkOption { 602 type = lib.types.int; 603 description = "TTL for the lock in seconds."; 604 default = 900; 605 example = 1; 606 }; 607 timeout = lib.mkOption { 608 type = lib.types.int; 609 description = "Timeout for the lock in seconds."; 610 default = 15; 611 example = 1; 612 }; 613 maxRetries = lib.mkOption { 614 type = lib.types.int; 615 description = "Maximum number of retries for the lock."; 616 default = 10; 617 example = 1; 618 }; 619 }; 620 }; 621 622 redisSentinel = { 623 endpoints = lib.mkOption { 624 type = lib.types.listOf lib.types.str; 625 description = "URLs that determine all distributed redis servers."; 626 default = [ ]; 627 example = [ "localhost:26379" ]; 628 }; 629 masterName = lib.mkOption { 630 type = lib.types.str; 631 description = "Name of the sentinel master server."; 632 default = ""; 633 example = "redis-1"; 634 }; 635 sentinelPassword = lib.mkOption { 636 type = lib.types.str; 637 description = "Password for the sentinel server. Warning: this is stored in plain text in the config file."; 638 default = ""; 639 example = "swordfish"; 640 }; 641 642 lockConfig = { 643 ttl = lib.mkOption { 644 type = lib.types.int; 645 description = "TTL for the lock in seconds."; 646 default = 900; 647 example = 1; 648 }; 649 timeout = lib.mkOption { 650 type = lib.types.int; 651 description = "Timeout for the lock in seconds."; 652 default = 15; 653 example = 1; 654 }; 655 maxRetries = lib.mkOption { 656 type = lib.types.int; 657 description = "Maximum number of retries for the lock."; 658 default = 10; 659 example = 1; 660 }; 661 }; 662 }; 663 }; 664 665 storage = { 666 cdn = { 667 endpoint = lib.mkOption { 668 type = lib.types.nullOr lib.types.str; 669 description = "hostname of the CDN server."; 670 example = "cdn.example.com"; 671 default = null; 672 }; 673 }; 674 675 disk = { 676 rootPath = lib.mkOption { 677 type = lib.types.nullOr lib.types.path; 678 description = "Athens disk root folder."; 679 default = "/var/lib/athens"; 680 }; 681 }; 682 683 gcp = { 684 projectID = lib.mkOption { 685 type = lib.types.nullOr lib.types.str; 686 description = "GCP project ID."; 687 example = "my-project"; 688 default = null; 689 }; 690 bucket = lib.mkOption { 691 type = lib.types.nullOr lib.types.str; 692 description = "GCP backend storage bucket."; 693 example = "my-bucket"; 694 default = null; 695 }; 696 jsonKey = lib.mkOption { 697 type = lib.types.nullOr lib.types.str; 698 description = "Base64 encoded GCP service account key. Warning: this is stored in plain text in the config file."; 699 default = null; 700 }; 701 }; 702 703 minio = { 704 endpoint = lib.mkOption { 705 type = lib.types.nullOr lib.types.str; 706 description = "Endpoint of the minio storage backend."; 707 example = "minio.example.com:9001"; 708 default = null; 709 }; 710 key = lib.mkOption { 711 type = lib.types.nullOr lib.types.str; 712 description = "Access key id for the minio storage backend."; 713 example = "minio"; 714 default = null; 715 }; 716 secret = lib.mkOption { 717 type = lib.types.nullOr lib.types.str; 718 description = "Secret key for the minio storage backend. Warning: this is stored in plain text in the config file."; 719 example = "minio123"; 720 default = null; 721 }; 722 enableSSL = lib.mkOption { 723 type = lib.types.bool; 724 description = "Enable SSL for the minio storage backend."; 725 default = false; 726 }; 727 bucket = lib.mkOption { 728 type = lib.types.nullOr lib.types.str; 729 description = "Bucket name for the minio storage backend."; 730 example = "gomods"; 731 default = null; 732 }; 733 region = lib.mkOption { 734 type = lib.types.nullOr lib.types.str; 735 description = "Region for the minio storage backend."; 736 example = "us-east-1"; 737 default = null; 738 }; 739 }; 740 741 mongo = { 742 url = lib.mkOption { 743 type = lib.types.nullOr lib.types.str; 744 description = "URL of the mongo database."; 745 example = "mongodb://localhost:27017"; 746 default = null; 747 }; 748 defaultDBName = lib.mkOption { 749 type = lib.types.nullOr lib.types.str; 750 description = "Name of the mongo database."; 751 example = "athens"; 752 default = null; 753 }; 754 certPath = lib.mkOption { 755 type = lib.types.nullOr lib.types.path; 756 description = "Path to the certificate file for the mongo database."; 757 example = "/etc/ssl/mongo.pem"; 758 default = null; 759 }; 760 insecure = lib.mkOption { 761 type = lib.types.bool; 762 description = "Allow insecure connections to the mongo database."; 763 default = false; 764 }; 765 }; 766 767 s3 = { 768 region = lib.mkOption { 769 type = lib.types.nullOr lib.types.str; 770 description = "Region of the S3 storage backend."; 771 example = "eu-west-3"; 772 default = null; 773 }; 774 key = lib.mkOption { 775 type = lib.types.nullOr lib.types.str; 776 description = "Access key id for the S3 storage backend."; 777 example = "minio"; 778 default = null; 779 }; 780 secret = lib.mkOption { 781 type = lib.types.str; 782 description = "Secret key for the S3 storage backend. Warning: this is stored in plain text in the config file."; 783 default = ""; 784 }; 785 token = lib.mkOption { 786 type = lib.types.nullOr lib.types.str; 787 description = "Token for the S3 storage backend. Warning: this is stored in plain text in the config file."; 788 default = null; 789 }; 790 bucket = lib.mkOption { 791 type = lib.types.nullOr lib.types.str; 792 description = "Bucket name for the S3 storage backend."; 793 example = "gomods"; 794 default = null; 795 }; 796 forcePathStyle = lib.mkOption { 797 type = lib.types.bool; 798 description = "Force path style for the S3 storage backend."; 799 default = false; 800 }; 801 useDefaultConfiguration = lib.mkOption { 802 type = lib.types.bool; 803 description = "Use default configuration for the S3 storage backend."; 804 default = false; 805 }; 806 credentialsEndpoint = lib.mkOption { 807 type = lib.types.str; 808 description = "Credentials endpoint for the S3 storage backend."; 809 default = ""; 810 }; 811 awsContainerCredentialsRelativeURI = lib.mkOption { 812 type = lib.types.nullOr lib.types.str; 813 description = "Container relative url (used by fargate)."; 814 default = null; 815 }; 816 endpoint = lib.mkOption { 817 type = lib.types.nullOr lib.types.str; 818 description = "Endpoint for the S3 storage backend."; 819 default = null; 820 }; 821 }; 822 823 azureblob = { 824 accountName = lib.mkOption { 825 type = lib.types.nullOr lib.types.str; 826 description = "Account name for the Azure Blob storage backend."; 827 default = null; 828 }; 829 accountKey = lib.mkOption { 830 type = lib.types.nullOr lib.types.str; 831 description = "Account key for the Azure Blob storage backend. Warning: this is stored in plain text in the config file."; 832 default = null; 833 }; 834 containerName = lib.mkOption { 835 type = lib.types.nullOr lib.types.str; 836 description = "Container name for the Azure Blob storage backend."; 837 default = null; 838 }; 839 }; 840 841 external = { 842 url = lib.mkOption { 843 type = lib.types.nullOr lib.types.str; 844 description = "URL of the backend storage layer."; 845 example = "https://athens.example.com"; 846 default = null; 847 }; 848 }; 849 }; 850 851 index = { 852 mysql = { 853 protocol = lib.mkOption { 854 type = lib.types.str; 855 description = "Protocol for the MySQL database."; 856 default = "tcp"; 857 }; 858 host = lib.mkOption { 859 type = lib.types.str; 860 description = "Host for the MySQL database."; 861 default = "localhost"; 862 }; 863 port = lib.mkOption { 864 type = lib.types.int; 865 description = "Port for the MySQL database."; 866 default = 3306; 867 }; 868 user = lib.mkOption { 869 type = lib.types.str; 870 description = "User for the MySQL database."; 871 default = "root"; 872 }; 873 password = lib.mkOption { 874 type = lib.types.nullOr lib.types.str; 875 description = "Password for the MySQL database. Warning: this is stored in plain text in the config file."; 876 default = null; 877 }; 878 database = lib.mkOption { 879 type = lib.types.str; 880 description = "Database name for the MySQL database."; 881 default = "athens"; 882 }; 883 params = { 884 parseTime = lib.mkOption { 885 type = lib.types.nullOr lib.types.str; 886 description = "Parse time for the MySQL database."; 887 default = "true"; 888 }; 889 timeout = lib.mkOption { 890 type = lib.types.nullOr lib.types.str; 891 description = "Timeout for the MySQL database."; 892 default = "30s"; 893 }; 894 }; 895 }; 896 897 postgres = { 898 host = lib.mkOption { 899 type = lib.types.str; 900 description = "Host for the Postgres database."; 901 default = "localhost"; 902 }; 903 port = lib.mkOption { 904 type = lib.types.int; 905 description = "Port for the Postgres database."; 906 default = 5432; 907 }; 908 user = lib.mkOption { 909 type = lib.types.str; 910 description = "User for the Postgres database."; 911 default = "postgres"; 912 }; 913 password = lib.mkOption { 914 type = lib.types.nullOr lib.types.str; 915 description = "Password for the Postgres database. Warning: this is stored in plain text in the config file."; 916 default = null; 917 }; 918 database = lib.mkOption { 919 type = lib.types.str; 920 description = "Database name for the Postgres database."; 921 default = "athens"; 922 }; 923 params = { 924 connect_timeout = lib.mkOption { 925 type = lib.types.nullOr lib.types.str; 926 description = "Connect timeout for the Postgres database."; 927 default = "30s"; 928 }; 929 sslmode = lib.mkOption { 930 type = lib.types.nullOr lib.types.str; 931 description = "SSL mode for the Postgres database."; 932 default = "disable"; 933 }; 934 }; 935 }; 936 }; 937 938 extraConfig = lib.mkOption { 939 type = lib.types.attrs; 940 description = '' 941 Extra configuration options for the athens config file. 942 ''; 943 default = { }; 944 }; 945 }; 946 947 config = lib.mkIf cfg.enable { 948 systemd.services.athens = { 949 description = "Athens Go module proxy"; 950 documentation = [ "https://docs.gomods.io" ]; 951 952 wantedBy = [ "multi-user.target" ]; 953 after = [ "network-online.target" ]; 954 wants = [ "network-online.target" ]; 955 956 serviceConfig = { 957 Restart = "on-abnormal"; 958 Nice = 5; 959 ExecStart = ''${cfg.package}/bin/athens -config_file=${configFile}''; 960 961 KillMode = "mixed"; 962 KillSignal = "SIGINT"; 963 TimeoutStopSec = cfg.shutdownTimeout; 964 965 LimitNOFILE = 1048576; 966 LimitNPROC = 512; 967 968 DynamicUser = true; 969 PrivateTmp = true; 970 PrivateDevices = true; 971 ProtectHome = "read-only"; 972 ProtectSystem = "full"; 973 974 ReadWritePaths = lib.mkIf ( 975 cfg.storage.disk.rootPath != null && (!lib.hasPrefix "/var/lib/" cfg.storage.disk.rootPath) 976 ) [ cfg.storage.disk.rootPath ]; 977 StateDirectory = lib.mkIf (lib.hasPrefix "/var/lib/" cfg.storage.disk.rootPath) [ 978 (lib.removePrefix "/var/lib/" cfg.storage.disk.rootPath) 979 ]; 980 981 CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ]; 982 AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; 983 NoNewPrivileges = true; 984 }; 985 }; 986 987 networking.firewall = { 988 allowedTCPPorts = 989 lib.optionals (cfg.unixSocket == null) [ cfg.port ] 990 ++ lib.optionals cfg.enablePprof [ cfg.pprofPort ]; 991 }; 992 }; 993 994}