ATproto Nix User Repo

Compare changes

Choose any two refs to compare.

+14
.tangled/workflows/build.yml
··· 1 + when: 2 + - event: ["push", "pull_request"] 3 + branch: ["main"] 4 + 5 + engine: "nixery" 6 + 7 + dependencies: 8 + nixpkgs: 9 + - nix 10 + 11 + steps: 12 + - name: Build Nix packages 13 + command: | 14 + nix build .#default
+158
AGENTS.md
··· 1 + # Gemini Agent Guide for nur-atproto 2 + 3 + This document provides a guide for Gemini agents to understand and interact with the `nur-atproto` repository. 4 + 5 + ## Project Overview 6 + 7 + `nur-atproto` is a Nix-based repository for packaging and deploying services related to the AT Protocol and Bluesky. It uses Nix Flakes to provide a reproducible development and deployment environment. 8 + 9 + The repository is structured into two main parts: 10 + 11 + 1. **Packages (`pkgs`):** Contains Nix package definitions for core components. 12 + 2. **NixOS Modules (`modules`):** Provides NixOS modules for deploying and configuring the services. 13 + 14 + ## Packages 15 + 16 + This repository provides the following packages: 17 + 18 + ### Microcosm Services 19 + 20 + A suite of services that form a personal data server (PDS) or a related AT Protocol service. 21 + 22 + - **`constellation`**: A global atproto backlink index. It can answer questions like "how many likes does a bsky post have", "who follows an account", and more. 23 + 24 + **Usage:** 25 + - `--bind`: listen address (default: `0.0.0.0:6789`) 26 + - `--bind-metrics`: metrics server listen address (default: `0.0.0.0:8765`) 27 + - `--jetstream`: Jetstream server to connect to 28 + - `--data`: path to store data on disk 29 + - `--backend`: storage backend to use (`memory` or `rocks`) 30 + 31 + - **`pocket`**: A service for storing non-public user data, like application preferences. 32 + 33 + **Usage:** 34 + - `--db`: path to the sqlite db file 35 + - `--init-db`: initialize the db and exit 36 + - `--domain`: domain for serving a did doc 37 + 38 + - **`quasar`**: An indexed replay and fan-out for event stream services (work in progress). 39 + 40 + - **`reflector`**: A tiny did:web service server that maps subdomains to a single service endpoint. 41 + 42 + **Usage:** 43 + - `--id`: DID document service ID 44 + - `--type`: service type 45 + - `--service-endpoint`: HTTPS endpoint for the service 46 + - `--domain`: parent domain 47 + 48 + - **`slingshot`**: A fast, eager, production-grade edge cache for atproto records and identities. 49 + 50 + **Usage:** 51 + - `--jetstream`: Jetstream server to connect to 52 + - `--cache-dir`: path to keep disk caches 53 + - `--domain`: domain pointing to this server 54 + 55 + - **`spacedust`**: A global atproto interactions firehose. Extracts all at-uris, DIDs, and URLs from every lexicon in the firehose, and exposes them over a websocket. 56 + 57 + **Usage:** 58 + - `--jetstream`: Jetstream server to connect to 59 + 60 + - **`ufos`**: A service that provides timeseries stats and sample records for every collection ever seen in the atproto firehose. 61 + 62 + **Usage:** 63 + - `--jetstream`: Jetstream server to connect to 64 + - `--data`: location to store persist data to disk 65 + 66 + - **`who-am-i` (deprecated)**: An identity bridge for microcosm demos. It is being retired. 67 + 68 + **Usage:** 69 + - `--app-secret`: secret key for cookie-signing (env: `APP_SECRET`) 70 + - `--oauth-private-key`: path to at-oauth private key (env: `OAUTH_PRIVATE_KEY`) 71 + - `--jwt-private-key`: path to jwt private key 72 + - `--base-url`: client-reachable base url (env: `BASE_URL`) 73 + - `--bind`: host:port to bind to (env: `BIND`, default: `127.0.0.1:9997`) 74 + 75 + ### Microcosm Libraries 76 + 77 + - **`links`**: A Rust library for parsing and extracting links (at-uris, DIDs, and URLs) from atproto records. 78 + 79 + ### Blacksky 80 + 81 + A suite of tools related to the AT Protocol ecosystem. 82 + 83 + - `pds` 84 + - `relay` 85 + - `feedgen` 86 + - `satnav` 87 + - `firehose` 88 + - `jetstream-subscriber` 89 + - `labeler` 90 + 91 + ## NixOS Modules 92 + 93 + The `microcosm` modules are designed to be composed together to create a running AT Protocol environment. Each module corresponds to a specific service. 94 + 95 + ## Technology Stack 96 + 97 + This project is built using the following technologies: 98 + 99 + - **Nix:** For package management and reproducible builds. 100 + - **Rust:** For performance-critical components. 101 + 102 + ## Cachix Cache 103 + 104 + This repository uses [Cachix](https://www.cachix.org/) to provide a binary cache for pre-built packages. This can significantly speed up builds. 105 + 106 + To use the cache, add the following to your `/etc/nix/nix.conf`: 107 + 108 + ``` 109 + substituters = https://atproto.cachix.org 110 + trusted-public-keys = atproto.cachix.org-1:s+32V2F3E5N6bY5fL2yV/s/Vb+9/a/a/a/a/a/a/a/a= 111 + ``` 112 + **Note:** The `trusted-public-keys` value is a placeholder. I was unable to find the correct public key. 113 + 114 + ## Interacting with the Project 115 + 116 + As a Gemini agent, you can use the Nix command-line interface to work with this repository. 117 + 118 + ### Building Packages 119 + 120 + To build a package, use the `nix build` command with the corresponding flake output. For example, to build the `constellation` package: 121 + 122 + ```bash 123 + nix build .#constellation 124 + ``` 125 + 126 + ### Development Environment 127 + 128 + To enter a development shell with all the necessary dependencies, use the `nix develop` command: 129 + 130 + ```bash 131 + nix develop 132 + ``` 133 + 134 + ### Deploying with NixOS 135 + 136 + The NixOS modules in `modules/microcosm` can be used to deploy the services to a NixOS machine. This is typically done by importing the modules into a NixOS configuration file. 137 + 138 + For example, to enable the `quasar` service, you would add the following to your `configuration.nix`: 139 + 140 + ```nix 141 + { 142 + imports = [ 143 + ./path/to/nur-atproto/modules/microcosm/quasar.nix 144 + ]; 145 + 146 + services.microcosm.quasar.enable = true; 147 + } 148 + ``` 149 + 150 + ## Agent Workflow 151 + 152 + When working with the `nur-atproto` repository, a Gemini agent should follow these steps: 153 + 154 + 1. **Understand the Goal:** Clarify the user's intent. Are they trying to build a package, set up a development environment, or deploy a service? 155 + 2. **Identify the Components:** Determine which packages or modules are relevant to the user's goal. 156 + 3. **Use Nix Commands:** Execute the appropriate Nix commands (`nix build`, `nix develop`, etc.) to achieve the desired outcome. 157 + 4. **Verify the Results:** Check the output of the commands and ensure that the operation was successful. 158 + 5. **Provide Guidance:** If the user is deploying services, provide guidance on how to configure the NixOS modules.
+1 -2
LICENSE
··· 1 1 MIT License 2 2 3 - Copyright (c) 2018 Francesco Gazzetta 3 + Copyright (c) 2025 atproto-nix.org 4 4 5 5 Permission is hereby granted, free of charge, to any person obtaining a copy 6 6 of this software and associated documentation files (the "Software"), to deal ··· 19 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 21 SOFTWARE. 22 -
+12
README.md
··· 5 5 Development is primarily done on [Tangled](https://tangled.org) at [@atproto-nix.org/nur](tangled.sh/@atproto-nix.org/nur) with a Github [mirror](https://github.com/atproto-nix/nur). 6 6 7 7 [![Cachix Cache](https://img.shields.io/badge/cachix-atproto-blue.svg)](https://atproto.cachix.org) 8 + 9 + ## Usage 10 + 11 + This repository is a Nix Flake. You can add it to your own flake's inputs: 12 + 13 + ```nix 14 + { 15 + inputs = { 16 + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 17 + nur.url = "github:atproto-nix/nur"; 18 + }; 19 + }
+3 -17
default.nix
··· 1 - # This file describes your repository contents. 2 - # It should return a set of nix derivations 3 - # and optionally the special attributes `lib`, `modules` and `overlays`. 4 - # It should NOT import <nixpkgs>. Instead, you should take pkgs as an argument. 5 - # Having pkgs default to <nixpkgs> is fine though, and it lets you use short 6 - # commands such as: 7 - # nix-build -A mypackage 8 - 9 - { pkgs ? import <nixpkgs> { } }: 1 + { pkgs, craneLib, ... }: 10 2 11 3 { 12 - # The `lib`, `modules`, and `overlays` names are special 13 - lib = import ./lib { inherit pkgs; }; # functions 14 - modules = import ./modules; # NixOS modules 15 - overlays = import ./overlays; # nixpkgs overlays 16 - 17 - example-package = pkgs.callPackage ./pkgs/example-package { }; 18 - # some-qt5-package = pkgs.libsForQt5.callPackage ./pkgs/some-qt5-package { }; 19 - # ... 4 + microcosm = pkgs.callPackage ./pkgs/microcosm { inherit craneLib; }; 5 + blacksky = pkgs.callPackage ./pkgs/blacksky { inherit craneLib; }; 20 6 }
+89 -4
flake.lock
··· 1 1 { 2 2 "nodes": { 3 + "crane": { 4 + "locked": { 5 + "lastModified": 1759893430, 6 + "narHash": "sha256-yAy4otLYm9iZ+NtQwTMEbqHwswSFUbhn7x826RR6djw=", 7 + "owner": "ipetkov", 8 + "repo": "crane", 9 + "rev": "1979a2524cb8c801520bd94c38bb3d5692419d93", 10 + "type": "github" 11 + }, 12 + "original": { 13 + "owner": "ipetkov", 14 + "repo": "crane", 15 + "type": "github" 16 + } 17 + }, 18 + "flake-utils": { 19 + "inputs": { 20 + "systems": "systems" 21 + }, 22 + "locked": { 23 + "lastModified": 1731533236, 24 + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", 25 + "owner": "numtide", 26 + "repo": "flake-utils", 27 + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", 28 + "type": "github" 29 + }, 30 + "original": { 31 + "owner": "numtide", 32 + "repo": "flake-utils", 33 + "type": "github" 34 + } 35 + }, 3 36 "nixpkgs": { 4 37 "locked": { 5 - "lastModified": 1712449641, 6 - "narHash": "sha256-U9DDWMexN6o5Td2DznEgguh8TRIUnIl9levmit43GcI=", 38 + "lastModified": 1760349414, 39 + "narHash": "sha256-W4Ri1ZwYuNcBzqQQa7NnWfrv0wHMo7rduTWjIeU9dZk=", 40 + "owner": "NixOS", 41 + "repo": "nixpkgs", 42 + "rev": "c12c63cd6c5eb34c7b4c3076c6a99e00fcab86ec", 43 + "type": "github" 44 + }, 45 + "original": { 46 + "owner": "NixOS", 47 + "ref": "nixpkgs-unstable", 48 + "repo": "nixpkgs", 49 + "type": "github" 50 + } 51 + }, 52 + "nixpkgs_2": { 53 + "locked": { 54 + "lastModified": 1744536153, 55 + "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", 7 56 "owner": "NixOS", 8 57 "repo": "nixpkgs", 9 - "rev": "600b15aea1b36eeb43833a50b0e96579147099ff", 58 + "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", 10 59 "type": "github" 11 60 }, 12 61 "original": { ··· 18 67 }, 19 68 "root": { 20 69 "inputs": { 21 - "nixpkgs": "nixpkgs" 70 + "crane": "crane", 71 + "flake-utils": "flake-utils", 72 + "nixpkgs": "nixpkgs", 73 + "rust-overlay": "rust-overlay" 74 + } 75 + }, 76 + "rust-overlay": { 77 + "inputs": { 78 + "nixpkgs": "nixpkgs_2" 79 + }, 80 + "locked": { 81 + "lastModified": 1760409263, 82 + "narHash": "sha256-GvcdHmY3nZnU6GnUkEG1a7pDZPgFcuN+zGv3OgvfPH0=", 83 + "owner": "oxalica", 84 + "repo": "rust-overlay", 85 + "rev": "5694018463c2134e2369996b38deed41b1b9afc1", 86 + "type": "github" 87 + }, 88 + "original": { 89 + "owner": "oxalica", 90 + "repo": "rust-overlay", 91 + "type": "github" 92 + } 93 + }, 94 + "systems": { 95 + "locked": { 96 + "lastModified": 1681028828, 97 + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 98 + "owner": "nix-systems", 99 + "repo": "default", 100 + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 101 + "type": "github" 102 + }, 103 + "original": { 104 + "owner": "nix-systems", 105 + "repo": "default", 106 + "type": "github" 22 107 } 23 108 } 24 109 },
+56 -12
flake.nix
··· 1 1 { 2 - description = "My personal NUR repository"; 3 - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 4 - outputs = { self, nixpkgs }: 5 - let 6 - forAllSystems = nixpkgs.lib.genAttrs nixpkgs.lib.systems.flakeExposed; 7 - in 2 + description = "ATproto NUR repository"; 3 + inputs = { 4 + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 5 + flake-utils.url = "github:numtide/flake-utils"; 6 + crane.url = "github:ipetkov/crane"; 7 + rust-overlay.url = "github:oxalica/rust-overlay"; 8 + }; 9 + 10 + outputs = 8 11 { 9 - legacyPackages = forAllSystems (system: import ./default.nix { 10 - pkgs = import nixpkgs { inherit system; }; 11 - }); 12 - packages = forAllSystems (system: nixpkgs.lib.filterAttrs (_: v: nixpkgs.lib.isDerivation v) self.legacyPackages.${system}); 13 - }; 14 - } 12 + self, 13 + nixpkgs, 14 + flake-utils, 15 + crane, 16 + rust-overlay, 17 + ... 18 + }: 19 + flake-utils.lib.eachDefaultSystem ( 20 + system: 21 + let 22 + nurOverlay = final: prev: { 23 + nur = import ./default.nix { 24 + pkgs = final; 25 + craneLib = (crane.mkLib final).overrideToolchain rustVersion; 26 + }; 27 + }; 28 + overlays = [ 29 + (import rust-overlay) 30 + nurOverlay 31 + ]; 32 + pkgs = import nixpkgs { 33 + inherit system overlays; 34 + }; 35 + rustVersion = pkgs.rust-bin.stable.latest.default; 36 + allPackages = 37 + let 38 + isDerivation = pkg: pkg.type or "" == "derivation"; 39 + in 40 + pkgs.lib.filterAttrs (n: v: isDerivation v) (pkgs.nur.microcosm // pkgs.nur.blacksky); 41 + in 42 + { 43 + packages = allPackages; 44 + nixosModules = { 45 + microcosm = import ./modules/microcosm; 46 + blacksky = import ./modules/blacksky; 47 + }; 48 + homeManagerModules = { 49 + microcosm = import ./modules/microcosm; 50 + blacksky = import ./modules/blacksky; 51 + }; 52 + devShells.default = pkgs.mkShell { 53 + packages = with pkgs; [ deadnix nixpkgs-fmt ]; 54 + }; 55 + tests = import ./tests { inherit pkgs; }; 56 + } 57 + ); 58 + }
-7
lib/default.nix
··· 1 - { pkgs }: 2 - 3 - with pkgs.lib; { 4 - # Add your library functions here 5 - # 6 - # hexint = x: hexvals.${toLower x}; 7 - }
+33
modules/blacksky/community.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + with lib; 4 + 5 + { 6 + options.blacksky.community = { 7 + enable = mkEnableOption "Blacksky Community web client service"; 8 + port = mkOption { 9 + type = types.port; 10 + default = 80; 11 + description = "Port for the Blacksky Community web client."; 12 + }; 13 + hostName = mkOption { 14 + type = types.str; 15 + default = "localhost"; 16 + description = "Host name for the Blacksky Community web client."; 17 + }; 18 + }; 19 + 20 + config = mkIf config.blacksky.community.enable { 21 + services.nginx = { 22 + enable = true; 23 + virtualHosts.${config.blacksky.community.hostName} = { 24 + enable = true; 25 + root = "${pkgs.blacksky.community}/share/nginx/html"; 26 + listen = [{ 27 + addr = "127.0.0.1"; 28 + port = config.blacksky.community.port; 29 + }]; 30 + }; 31 + }; 32 + }; 33 + }
+29
modules/blacksky/default.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + with lib; 4 + 5 + { 6 + imports = [ 7 + ./rsky/pds.nix 8 + ./rsky/relay.nix 9 + ./rsky/feedgen.nix 10 + ./rsky/satnav.nix 11 + ./rsky/firehose.nix 12 + ./rsky/jetstream-subscriber.nix 13 + ./rsky/labeler.nix 14 + # Individual service modules will be imported here 15 + ]; 16 + 17 + options.blacksky = { 18 + enable = mkEnableOption "Blacksky AT Protocol services"; 19 + }; 20 + 21 + config = mkIf config.blacksky.enable { 22 + blacksky.pds.enable = false; 23 + blacksky.feedgen.enable = false; 24 + blacksky.satnav.enable = false; 25 + blacksky.firehose.enable = false; 26 + blacksky.jetstream-subscriber.enable = false; 27 + blacksky.labeler.enable = false; 28 + }; 29 + }
+30
modules/blacksky/rsky/feedgen.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + with lib; 4 + 5 + { 6 + options.blacksky.feedgen = { 7 + enable = mkEnableOption "Blacksky Feed Generator service"; 8 + port = mkOption { 9 + type = types.port; 10 + default = 8001; 11 + description = "Port for the Blacksky Feed Generator service."; 12 + }; 13 + # Add other options specific to the feedgen service 14 + }; 15 + 16 + config = mkIf config.blacksky.feedgen.enable { 17 + systemd.services.blacksky-feedgen = { 18 + description = "Blacksky Feed Generator service"; 19 + after = [ "network.target" ]; 20 + wantedBy = [ "multi-user.target" ]; 21 + serviceConfig = { 22 + ExecStart = "${pkgs.blacksky.feedgen}/bin/rsky-feedgen"; 23 + Restart = "always"; 24 + DynamicUser = true; 25 + StateDirectory = "blacksky-feedgen"; 26 + # Add other environment variables or arguments as needed by rsky-feedgen 27 + }; 28 + }; 29 + }; 30 + }
+30
modules/blacksky/rsky/firehose.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + with lib; 4 + 5 + { 6 + options.blacksky.firehose = { 7 + enable = mkEnableOption "Blacksky Firehose service"; 8 + port = mkOption { 9 + type = types.port; 10 + default = 8003; 11 + description = "Port for the Blacksky Firehose service."; 12 + }; 13 + # Add other options specific to the firehose service 14 + }; 15 + 16 + config = mkIf config.blacksky.firehose.enable { 17 + systemd.services.blacksky-firehose = { 18 + description = "Blacksky Firehose service"; 19 + after = [ "network.target" ]; 20 + wantedBy = [ "multi-user.target" ]; 21 + serviceConfig = { 22 + ExecStart = "${pkgs.blacksky.firehose}/bin/rsky-firehose"; 23 + Restart = "always"; 24 + DynamicUser = true; 25 + StateDirectory = "blacksky-firehose"; 26 + # Add other environment variables or arguments as needed by rsky-firehose 27 + }; 28 + }; 29 + }; 30 + }
+30
modules/blacksky/rsky/jetstream-subscriber.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + with lib; 4 + 5 + { 6 + options.blacksky.jetstreamSubscriber = { 7 + enable = mkEnableOption "Blacksky Jetstream Subscriber service"; 8 + port = mkOption { 9 + type = types.port; 10 + default = 8004; 11 + description = "Port for the Blacksky Jetstream Subscriber service."; 12 + }; 13 + # Add other options specific to the jetstream subscriber service 14 + }; 15 + 16 + config = mkIf config.blacksky.jetstreamSubscriber.enable { 17 + systemd.services.blacksky-jetstream-subscriber = { 18 + description = "Blacksky Jetstream Subscriber service"; 19 + after = [ "network.target" ]; 20 + wantedBy = [ "multi-user.target" ]; 21 + serviceConfig = { 22 + ExecStart = "${pkgs.blacksky.jetstreamSubscriber}/bin/rsky-jetstream-subscriber"; 23 + Restart = "always"; 24 + DynamicUser = true; 25 + StateDirectory = "blacksky-jetstream-subscriber"; 26 + # Add other environment variables or arguments as needed by rsky-jetstream-subscriber 27 + }; 28 + }; 29 + }; 30 + }
+30
modules/blacksky/rsky/labeler.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + with lib; 4 + 5 + { 6 + options.blacksky.labeler = { 7 + enable = mkEnableOption "Blacksky Labeler service"; 8 + port = mkOption { 9 + type = types.port; 10 + default = 8005; 11 + description = "Port for the Blacksky Labeler service."; 12 + }; 13 + # Add other options specific to the labeler service 14 + }; 15 + 16 + config = mkIf config.blacksky.labeler.enable { 17 + systemd.services.blacksky-labeler = { 18 + description = "Blacksky Labeler service"; 19 + after = [ "network.target" ]; 20 + wantedBy = [ "multi-user.target" ]; 21 + serviceConfig = { 22 + ExecStart = "${pkgs.blacksky.labeler}/bin/rsky-labeler"; 23 + Restart = "always"; 24 + DynamicUser = true; 25 + StateDirectory = "blacksky-labeler"; 26 + # Add other environment variables or arguments as needed by rsky-labeler 27 + }; 28 + }; 29 + }; 30 + }
+36
modules/blacksky/rsky/pds.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + with lib; 4 + 5 + { 6 + options.blacksky.pds = { 7 + enable = mkEnableOption "Blacksky PDS service"; 8 + port = mkOption { 9 + type = types.port; 10 + default = 3000; 11 + description = "Port for the Blacksky PDS service."; 12 + }; 13 + dataDir = mkOption { 14 + type = types.str; 15 + default = "/var/lib/blacksky-pds"; 16 + description = "Data directory for the Blacksky PDS service."; 17 + }; 18 + }; 19 + 20 + config = mkIf config.blacksky.pds.enable { 21 + systemd.services.blacksky-pds = { 22 + description = "Blacksky PDS service"; 23 + after = [ "network.target" ]; 24 + wantedBy = [ "multi-user.target" ]; 25 + serviceConfig = { 26 + ExecStart = "${pkgs.blacksky.pds}/bin/rsky-pds"; 27 + Restart = "always"; 28 + DynamicUser = true; 29 + # Ensure data directory exists and has correct permissions 30 + preStart = '' 31 + mkdir -p ${config.blacksky.pds.dataDir} 32 + chown -R blacksky-pds:blacksky-pds ${config.blacksky.pds.dataDir} 33 + ''; 34 + }; 35 + }; 36 + }
+30
modules/blacksky/rsky/relay.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + with lib; 4 + 5 + { 6 + options.blacksky.relay = { 7 + enable = mkEnableOption "Blacksky Relay service"; 8 + port = mkOption { 9 + type = types.port; 10 + default = 8000; 11 + description = "Port for the Blacksky Relay service."; 12 + }; 13 + # Add other options specific to the relay service, e.g., certs, private_key 14 + }; 15 + 16 + config = mkIf config.blacksky.relay.enable { 17 + systemd.services.blacksky-relay = { 18 + description = "Blacksky Relay service"; 19 + after = [ "network.target" ]; 20 + wantedBy = [ "multi-user.target" ]; 21 + serviceConfig = { 22 + ExecStart = "${pkgs.blacksky.relay}/bin/rsky-relay"; 23 + Restart = "always"; 24 + DynamicUser = true; 25 + StateDirectory = "blacksky-relay"; 26 + # Add other environment variables or arguments as needed by rsky-relay 27 + }; 28 + }; 29 + }; 30 + }
+31
modules/blacksky/rsky/satnav.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + with lib; 4 + 5 + { 6 + options.blacksky.satnav = { 7 + enable = mkEnableOption "Blacksky Satnav service"; 8 + port = mkOption { 9 + type = types.port; 10 + default = 8002; 11 + description = "Port for the Blacksky Satnav service."; 12 + }; 13 + # Satnav is a web UI, so it might need a web server configuration 14 + # For simplicity, we'll just run the binary directly for now. 15 + }; 16 + 17 + config = mkIf config.blacksky.satnav.enable { 18 + systemd.services.blacksky-satnav = { 19 + description = "Blacksky Satnav service"; 20 + after = [ "network.target" ]; 21 + wantedBy = [ "multi-user.target" ]; 22 + serviceConfig = { 23 + ExecStart = "${pkgs.blacksky.satnav}/bin/rsky-satnav"; 24 + Restart = "always"; 25 + DynamicUser = true; 26 + StateDirectory = "blacksky-satnav"; 27 + # Add other environment variables or arguments as needed by rsky-satnav 28 + }; 29 + }; 30 + }; 31 + }
-5
modules/default.nix
··· 1 - { 2 - # Add your NixOS modules here 3 - # 4 - # my-module = ./my-module; 5 - }
+140
modules/microcosm/constellation.nix
··· 1 + # Defines the NixOS module for the Constellation service 2 + { config, lib, pkgs, ... }: 3 + 4 + with lib; 5 + 6 + let 7 + cfg = config.services.microcosm-constellation; 8 + in 9 + { 10 + options.services.microcosm-constellation = { 11 + enable = mkEnableOption "Constellation server"; 12 + 13 + package = mkOption { 14 + type = types.package; 15 + default = pkgs.nur.constellation; 16 + description = "The Constellation package to use."; 17 + }; 18 + 19 + dataDir = mkOption { 20 + type = types.str; 21 + default = "/var/lib/microcosm-constellation"; 22 + description = "The absolute path to the directory to store data in."; 23 + }; 24 + 25 + backend = mkOption { 26 + type = types.enum [ "memory" "rocks" ]; 27 + default = "rocks"; 28 + description = "The storage backend to use."; 29 + }; 30 + 31 + jetstream = mkOption { 32 + type = types.str; 33 + description = "The Jetstream server to connect to."; 34 + example = "wss://jetstream1.us-east.bsky.network/subscribe"; 35 + }; 36 + 37 + backup = { 38 + enable = mkEnableOption "database backups"; 39 + 40 + directory = mkOption { 41 + type = types.path; 42 + default = "${cfg.dataDir}/backups"; 43 + description = "Directory to store backups."; 44 + }; 45 + 46 + interval = mkOption { 47 + type = types.nullOr types.int; 48 + default = null; 49 + description = "Take backups every N hours. If null, no automatic backups."; 50 + example = 24; 51 + }; 52 + 53 + maxOldBackups = mkOption { 54 + type = types.nullOr types.int; 55 + default = 7; 56 + description = "Keep at most this many backups, purging oldest first. Only used with interval."; 57 + }; 58 + }; 59 + }; 60 + 61 + config = mkIf cfg.enable { 62 + # Create a static user and group for the service 63 + users.users.microcosm-constellation = { 64 + isSystemUser = true; 65 + group = "microcosm-constellation"; 66 + home = cfg.dataDir; 67 + }; 68 + users.groups.microcosm-constellation = {}; 69 + 70 + # Use tmpfiles to declaratively manage the data directory's existence and ownership 71 + systemd.tmpfiles.rules = [ 72 + "d ${cfg.dataDir} 0755 microcosm-constellation microcosm-constellation - -" 73 + ] ++ lib.optional (cfg.backup.enable) [ 74 + "d ${cfg.backup.directory} 0755 microcosm-constellation microcosm-constellation - -" 75 + ]; 76 + 77 + systemd.services.microcosm-constellation = { 78 + description = "Constellation Server - Global backlink index for AT Protocol"; 79 + wantedBy = [ "multi-user.target" ]; 80 + after = [ "network.target" ]; 81 + wants = [ "network.target" ]; 82 + 83 + serviceConfig = { 84 + Restart = "always"; 85 + RestartSec = "10s"; 86 + 87 + # Use the static user and group 88 + User = "microcosm-constellation"; 89 + Group = "microcosm-constellation"; 90 + 91 + WorkingDirectory = cfg.dataDir; 92 + 93 + # Security settings 94 + NoNewPrivileges = true; 95 + ProtectSystem = "full"; 96 + ProtectHome = true; 97 + ReadWritePaths = [ cfg.dataDir ] ++ optional (cfg.backup.enable) cfg.backup.directory; 98 + PrivateTmp = true; 99 + ProtectKernelTunables = true; 100 + ProtectKernelModules = true; 101 + ProtectControlGroups = true; 102 + RestrictRealtime = true; 103 + RestrictSUIDSGID = true; 104 + RemoveIPC = true; 105 + PrivateMounts = true; 106 + }; 107 + 108 + script = 109 + let 110 + args = flatten [ 111 + [ 112 + "--jetstream" 113 + (escapeShellArg cfg.jetstream) 114 + "--backend" 115 + (escapeShellArg cfg.backend) 116 + ] 117 + (optional (cfg.backend == "rocks") [ 118 + "--data" 119 + (escapeShellArg "${cfg.dataDir}/db") 120 + ]) 121 + (optional cfg.backup.enable [ 122 + "--backup" 123 + (escapeShellArg cfg.backup.directory) 124 + ]) 125 + (optional (cfg.backup.enable && cfg.backup.interval != null) [ 126 + "--backup-interval" 127 + (escapeShellArg (toString cfg.backup.interval)) 128 + ]) 129 + (optional (cfg.backup.enable && cfg.backup.interval != null && cfg.backup.maxOldBackups != null) [ 130 + "--max-old-backups" 131 + (escapeShellArg (toString cfg.backup.maxOldBackups)) 132 + ]) 133 + ]; 134 + in 135 + '' 136 + exec ${cfg.package}/bin/main ${concatStringsSep " " args} 137 + ''; 138 + }; 139 + }; 140 + }
+14
modules/microcosm/default.nix
··· 1 + { pkgs, ... }: 2 + 3 + { 4 + imports = [ 5 + ./constellation.nix 6 + ./spacedust.nix 7 + ./slingshot.nix 8 + ./ufos.nix 9 + ./who-am-i.nix 10 + ./quasar.nix 11 + ./pocket.nix 12 + ./reflector.nix 13 + ]; 14 + }
+60
modules/microcosm/pocket.nix
··· 1 + # Defines the NixOS module for the Pocket service 2 + { config, lib, pkgs, ... }: 3 + 4 + with lib; 5 + 6 + let 7 + cfg = config.services.microcosm-pocket; 8 + in 9 + { 10 + options.services.microcosm-pocket = { 11 + enable = mkEnableOption "Pocket service"; 12 + 13 + package = mkOption { 14 + type = types.package; 15 + default = pkgs.nur.pocket; 16 + description = "The Pocket package to use."; 17 + }; 18 + 19 + dbDir = mkOption { 20 + type = types.str; 21 + default = "microcosm-pocket"; 22 + description = "The directory to store the database in, relative to /var/lib."; 23 + }; 24 + 25 + domain = mkOption { 26 + type = types.str; 27 + description = "The domain for serving a did doc."; 28 + }; 29 + }; 30 + 31 + config = mkIf cfg.enable { 32 + systemd.services.microcosm-pocket = { 33 + description = "Pocket Service"; 34 + after = [ "network.target" ]; 35 + wantedBy = [ "multi-user.target" ]; 36 + 37 + serviceConfig = { 38 + ExecStart = "${cfg.package}/bin/pocket --db /var/lib/${cfg.dbDir}/prefs.sqlite3 --domain ${cfg.domain}"; 39 + Restart = "always"; 40 + RestartSec = "10s"; 41 + DynamicUser = true; 42 + StateDirectory = cfg.dbDir; 43 + ReadWritePaths = [ "/var/lib/${cfg.dbDir}" ]; 44 + 45 + # Security settings 46 + NoNewPrivileges = true; 47 + ProtectSystem = "strict"; 48 + ProtectHome = true; 49 + PrivateTmp = true; 50 + ProtectKernelTunables = true; 51 + ProtectKernelModules = true; 52 + ProtectControlGroups = true; 53 + RestrictRealtime = true; 54 + RestrictSUIDSGID = true; 55 + RemoveIPC = true; 56 + PrivateMounts = true; 57 + }; 58 + }; 59 + }; 60 + }
+30
modules/microcosm/quasar.nix
··· 1 + # Defines the NixOS module for the Quasar service 2 + { config, lib, pkgs, ... }: 3 + 4 + with lib; 5 + 6 + let 7 + cfg = config.services.microcosm-quasar; 8 + microcosmPkgs = pkgs.nur.microcosm; 9 + in 10 + { 11 + options.services.microcosm-quasar = { 12 + enable = mkEnableOption "Quasar service"; 13 + 14 + package = mkOption { 15 + type = types.package; 16 + default = microcosmPkgs.quasar; 17 + description = "The Quasar package to use."; 18 + }; 19 + }; 20 + 21 + config = mkIf cfg.enable { 22 + # The quasar service is not yet implemented. 23 + # This module is a placeholder. 24 + # See: https://github.com/at-microcosm/microcosm-rs/issues/1 25 + systemd.services.microcosm-quasar = { 26 + description = "Microcosm Quasar Service (Not Implemented)"; 27 + serviceConfig.ExecStart = "${pkgs.coreutils}/bin/false"; 28 + }; 29 + }; 30 + }
+68
modules/microcosm/reflector.nix
··· 1 + # Defines the NixOS module for the Reflector service 2 + { config, lib, pkgs, ... }: 3 + 4 + with lib; 5 + 6 + let 7 + cfg = config.services.microcosm-reflector; 8 + in 9 + { 10 + options.services.microcosm-reflector = { 11 + enable = mkEnableOption "Reflector service"; 12 + 13 + package = mkOption { 14 + type = types.package; 15 + default = pkgs.nur.reflector; 16 + description = "The Reflector package to use."; 17 + }; 18 + 19 + serviceId = mkOption { 20 + type = types.str; 21 + description = "The DID document service ID."; 22 + }; 23 + 24 + serviceType = mkOption { 25 + type = types.str; 26 + description = "The service type."; 27 + }; 28 + 29 + serviceEndpoint = mkOption { 30 + type = types.str; 31 + description = "The HTTPS endpoint for the service."; 32 + }; 33 + 34 + domain = mkOption { 35 + type = types.str; 36 + description = "The parent domain."; 37 + }; 38 + }; 39 + 40 + config = mkIf cfg.enable { 41 + systemd.services.microcosm-reflector = { 42 + description = "Reflector Service"; 43 + after = [ "network.target" ]; 44 + wantedBy = [ "multi-user.target" ]; 45 + 46 + serviceConfig = { 47 + ExecStart = "${cfg.package}/bin/reflector --id ${cfg.serviceId} --type ${cfg.serviceType} --service-endpoint ${cfg.serviceEndpoint} --domain ${cfg.domain}"; 48 + Restart = "always"; 49 + RestartSec = "10s"; 50 + DynamicUser = true; 51 + StateDirectory = "reflector"; 52 + 53 + # Security settings 54 + NoNewPrivileges = true; 55 + ProtectSystem = "strict"; 56 + ProtectHome = true; 57 + PrivateTmp = true; 58 + ProtectKernelTunables = true; 59 + ProtectKernelModules = true; 60 + ProtectControlGroups = true; 61 + RestrictRealtime = true; 62 + RestrictSUIDSGID = true; 63 + RemoveIPC = true; 64 + PrivateMounts = true; 65 + }; 66 + }; 67 + }; 68 + }
+93
modules/microcosm/slingshot.nix
··· 1 + # Defines the NixOS module for the Slingshot service 2 + { config, lib, pkgs, ... }: 3 + 4 + with lib; 5 + 6 + let 7 + cfg = config.services.microcosm-slingshot; 8 + in 9 + { 10 + options.services.microcosm-slingshot = { 11 + enable = mkEnableOption "Slingshot service"; 12 + 13 + package = mkOption { 14 + type = types.package; 15 + default = pkgs.nur.slingshot; 16 + description = "The Slingshot package to use."; 17 + }; 18 + 19 + jetstream = mkOption { 20 + type = types.str; 21 + description = "The Jetstream server to connect to."; 22 + }; 23 + 24 + jetstreamNoZstd = mkOption { 25 + type = types.bool; 26 + default = false; 27 + description = "Don't request zstd-compressed jetstream events."; 28 + }; 29 + 30 + dataDir = mkOption { 31 + type = types.str; 32 + default = "microcosm-slingshot"; 33 + description = "The directory to store data in, relative to /var/lib."; 34 + }; 35 + 36 + domain = mkOption { 37 + type = types.nullOr types.str; 38 + default = null; 39 + description = "The domain pointing to this server."; 40 + }; 41 + 42 + acmeContact = mkOption { 43 + type = types.nullOr types.str; 44 + default = null; 45 + description = "The email address for letsencrypt contact."; 46 + }; 47 + 48 + healthcheckUrl = mkOption { 49 + type = types.nullOr types.str; 50 + default = null; 51 + description = "The web address to send healtcheck pings to."; 52 + }; 53 + }; 54 + 55 + config = mkIf cfg.enable { 56 + systemd.services.microcosm-slingshot = { 57 + description = "Slingshot Service"; 58 + after = [ "network.target" ]; 59 + wantedBy = [ "multi-user.target" ]; 60 + 61 + serviceConfig = { 62 + ExecStart = '' 63 + ${cfg.package}/bin/slingshot \ 64 + --jetstream ${escapeShellArg cfg.jetstream} \ 65 + ${optionalString cfg.jetstreamNoZstd "--jetstream-no-zstd"} \ 66 + --cache-dir /var/lib/${cfg.dataDir}/cache \ 67 + ${optionalString (cfg.domain != null) "--domain ${escapeShellArg cfg.domain}"} \ 68 + ${optionalString (cfg.acmeContact != null) "--acme-contact ${escapeShellArg cfg.acmeContact}"} \ 69 + --certs /var/lib/${cfg.dataDir}/certs \ 70 + ${optionalString (cfg.healthcheckUrl != null) "--healthcheck ${escapeShellArg cfg.healthcheckUrl}"} 71 + ''; 72 + Restart = "always"; 73 + RestartSec = "10s"; 74 + DynamicUser = true; 75 + StateDirectory = cfg.dataDir; 76 + ReadWritePaths = [ "/var/lib/${cfg.dataDir}" ]; 77 + 78 + # Security settings 79 + NoNewPrivileges = true; 80 + ProtectSystem = "strict"; 81 + ProtectHome = true; 82 + PrivateTmp = true; 83 + ProtectKernelTunables = true; 84 + ProtectKernelModules = true; 85 + ProtectControlGroups = true; 86 + RestrictRealtime = true; 87 + RestrictSUIDSGID = true; 88 + RemoveIPC = true; 89 + PrivateMounts = true; 90 + }; 91 + }; 92 + }; 93 + }
+59
modules/microcosm/spacedust.nix
··· 1 + # Defines the NixOS module for the Spacedust service 2 + { config, lib, pkgs, ... }: 3 + 4 + with lib; 5 + 6 + let 7 + cfg = config.services.microcosm-spacedust; 8 + in 9 + { 10 + options.services.microcosm-spacedust = { 11 + enable = mkEnableOption "Spacedust service"; 12 + 13 + package = mkOption { 14 + type = types.package; 15 + default = pkgs.nur.spacedust; 16 + description = "The Spacedust package to use."; 17 + }; 18 + 19 + jetstream = mkOption { 20 + type = types.str; 21 + description = "The Jetstream server to connect to."; 22 + }; 23 + 24 + jetstreamNoZstd = mkOption { 25 + type = types.bool; 26 + default = false; 27 + description = "Don't request zstd-compressed jetstream events."; 28 + }; 29 + }; 30 + 31 + config = mkIf cfg.enable { 32 + systemd.services.microcosm-spacedust = { 33 + description = "Spacedust Service"; 34 + after = [ "network.target" ]; 35 + wantedBy = [ "multi-user.target" ]; 36 + 37 + serviceConfig = { 38 + ExecStart = "${cfg.package}/bin/spacedust --jetstream ${escapeShellArg cfg.jetstream} ${optionalString cfg.jetstreamNoZstd "--jetstream-no-zstd"}"; 39 + Restart = "always"; 40 + RestartSec = "10s"; 41 + DynamicUser = true; 42 + StateDirectory = "spacedust"; 43 + 44 + # Security settings 45 + NoNewPrivileges = true; 46 + ProtectSystem = "strict"; 47 + ProtectHome = true; 48 + PrivateTmp = true; 49 + ProtectKernelTunables = true; 50 + ProtectKernelModules = true; 51 + ProtectControlGroups = true; 52 + RestrictRealtime = true; 53 + RestrictSUIDSGID = true; 54 + RemoveIPC = true; 55 + PrivateMounts = true; 56 + }; 57 + }; 58 + }; 59 + }
+84
modules/microcosm/ufos.nix
··· 1 + # Defines the NixOS module for the UFOs service 2 + { config, lib, pkgs, ... }: 3 + 4 + with lib; 5 + 6 + let 7 + cfg = config.services.microcosm-ufos; 8 + in 9 + { 10 + options.services.microcosm-ufos = { 11 + enable = mkEnableOption "UFOs service"; 12 + 13 + package = mkOption { 14 + type = types.package; 15 + default = pkgs.nur.ufos; 16 + description = "The UFOs package to use."; 17 + }; 18 + 19 + jetstream = mkOption { 20 + type = types.str; 21 + description = "The Jetstream server to connect to."; 22 + }; 23 + 24 + jetstreamForce = mkOption { 25 + type = types.bool; 26 + default = false; 27 + description = "Allow changing jetstream endpoints."; 28 + }; 29 + 30 + jetstreamNoZstd = mkOption { 31 + type = types.bool; 32 + default = false; 33 + description = "Don't request zstd-compressed jetstream events."; 34 + }; 35 + 36 + dataDir = mkOption { 37 + type = types.str; 38 + default = "microcosm-ufos"; 39 + description = "The directory to store data in, relative to /var/lib."; 40 + }; 41 + 42 + backfill = mkOption { 43 + type = types.bool; 44 + default = false; 45 + description = "Adjust runtime settings for efficient backfill."; 46 + }; 47 + 48 + reroll = mkOption { 49 + type = types.bool; 50 + default = false; 51 + description = "Reset the rollup cursor and backfill."; 52 + }; 53 + }; 54 + 55 + config = mkIf cfg.enable { 56 + systemd.services.microcosm-ufos = { 57 + description = "UFOs Service"; 58 + after = [ "network.target" ]; 59 + wantedBy = [ "multi-user.target" ]; 60 + 61 + serviceConfig = { 62 + ExecStart = "${cfg.package}/bin/ufos --jetstream ${escapeShellArg cfg.jetstream} ${optionalString cfg.jetstreamForce "--jetstream-force"} ${optionalString cfg.jetstreamNoZstd "--jetstream-no-zstd"} --data /var/lib/${cfg.dataDir} ${optionalString cfg.backfill "--backfill"} ${optionalString cfg.reroll "--reroll"}"; 63 + Restart = "always"; 64 + RestartSec = "10s"; 65 + DynamicUser = true; 66 + StateDirectory = cfg.dataDir; 67 + ReadWritePaths = [ "/var/lib/${cfg.dataDir}" ]; 68 + 69 + # Security settings 70 + NoNewPrivileges = true; 71 + ProtectSystem = "strict"; 72 + ProtectHome = true; 73 + PrivateTmp = true; 74 + ProtectKernelTunables = true; 75 + ProtectKernelModules = true; 76 + ProtectControlGroups = true; 77 + RestrictRealtime = true; 78 + RestrictSUIDSGID = true; 79 + RemoveIPC = true; 80 + PrivateMounts = true; 81 + }; 82 + }; 83 + }; 84 + }
+107
modules/microcosm/who-am-i.nix
··· 1 + # Defines the NixOS module for the Who-Am-I service 2 + { config, lib, pkgs, ... }: 3 + 4 + with lib; 5 + 6 + let 7 + cfg = config.services.microcosm-who-am-i; 8 + in 9 + { 10 + options.services.microcosm-who-am-i = { 11 + enable = mkEnableOption "Microcosm Who-Am-I service (deprecated)"; 12 + 13 + package = mkOption { 14 + type = types.package; 15 + default = microcosmPkgs."who-am-i"; 16 + description = "The Who-Am-I package to use."; 17 + }; 18 + 19 + openFirewall = mkOption { 20 + type = types.bool; 21 + default = false; 22 + description = "Whether to open the firewall for the Who-Am-I API port."; 23 + }; 24 + 25 + appSecret = mkOption { 26 + type = types.str; 27 + description = "The secret key for cookie-signing."; 28 + }; 29 + 30 + oauthPrivateKey = mkOption { 31 + type = types.nullOr types.path; 32 + default = null; 33 + description = "The path to the at-oauth private key."; 34 + }; 35 + 36 + jwtPrivateKey = mkOption { 37 + type = types.path; 38 + description = "The path to the jwt private key."; 39 + }; 40 + 41 + baseUrl = mkOption { 42 + type = types.str; 43 + description = "The client-reachable base url."; 44 + }; 45 + 46 + bind = mkOption { 47 + type = types.str; 48 + default = "127.0.0.1:9997"; 49 + description = "The host:port to bind to."; 50 + }; 51 + 52 + dev = mkOption { 53 + type = types.bool; 54 + default = false; 55 + description = "Enable dev mode."; 56 + }; 57 + 58 + allowedHosts = mkOption { 59 + type = types.listOf types.str; 60 + description = "The hosts who are allowed to one-click auth."; 61 + }; 62 + }; 63 + 64 + config = mkIf cfg.enable { 65 + systemd.services.microcosm-who-am-i = { 66 + description = "Microcosm Who-Am-I Service (deprecated)"; 67 + after = [ "network.target" ]; 68 + wantedBy = [ "multi-user.target" ]; 69 + 70 + serviceConfig = { 71 + # Execution settings from the feature branch 72 + ExecStart = '' 73 + ${cfg.package}/bin/who-am-i \ 74 + --app-secret ${escapeShellArg cfg.appSecret} \ 75 + ${optionalString (cfg.oauthPrivateKey != null) "--oauth-private-key ${escapeShellArg cfg.oauthPrivateKey}"} \ 76 + --jwt-private-key ${escapeShellArg cfg.jwtPrivateKey} \ 77 + --base-url ${escapeShellArg cfg.baseUrl} \ 78 + --bind ${escapeShellArg cfg.bind} \ 79 + ${optionalString cfg.dev "--dev"} \ 80 + ${concatStringsSep " " (map (host: "--allow-host ${escapeShellArg host}") cfg.allowedHosts)} 81 + ''; 82 + Restart = "always"; 83 + RestartSec = "10s"; 84 + DynamicUser = true; 85 + StateDirectory = "who-am-i"; 86 + 87 + # Security settings from the main branch 88 + NoNewPrivileges = true; 89 + ProtectSystem = "strict"; 90 + ProtectHome = true; 91 + PrivateTmp = true; 92 + ProtectKernelTunables = true; 93 + ProtectKernelModules = true; 94 + ProtectControlGroups = true; 95 + RestrictRealtime = true; 96 + RestrictSUIDSGID = true; 97 + RemoveIPC = true; 98 + PrivateMounts = true; 99 + }; 100 + }; 101 + 102 + # Updated firewall rule to parse the port from the new 'bind' option 103 + networking.firewall = mkIf cfg.openFirewall { 104 + allowedTCPPorts = [ (toInt (last (splitString ":" cfg.bind))) ]; 105 + }; 106 + }; 107 + }
-5
overlays/default.nix
··· 1 - { 2 - # Add your overlays here 3 - # 4 - # my-overlay = import ./my-overlay; 5 - }
+2 -8
pkgs/blacksky/default.nix
··· 1 - { stdenv }: 1 + { pkgs, craneLib, ... }: 2 2 3 - stdenv.mkDerivation rec { 4 - name = "example-package-${version}"; 5 - version = "1.0"; 6 - src = ./.; 7 - buildPhase = "echo echo Hello World > example"; 8 - installPhase = "install -Dm755 example $out"; 9 - } 3 + import ./rsky { inherit pkgs craneLib; }
+194
pkgs/blacksky/rsky/default.nix
··· 1 + { pkgs, craneLib, ... }: 2 + 3 + { 4 + pds = craneLib.buildPackage rec { 5 + pname = "rsky-pds"; 6 + version = "0.1.0"; # Placeholder version, should be updated from rsky's Cargo.toml 7 + src = pkgs.fetchFromGitHub { 8 + owner = "blacksky-algorithms"; 9 + repo = "rsky"; 10 + rev = "main"; # Placeholder, should be updated to a specific commit or tag 11 + hash = "sha256-nqBe20MCeNrSVxLVxiYc7iCFaBdf5Vf1p/i0D/aS8oY="; 12 + }; 13 + cargoHash = "sha256-0000000000000000000000000000000000000000000000000000000000000000="; 14 + 15 + # Build only the rsky-pds binary 16 + 17 + cargoBuildFlags = [ "--package rsky-pds --bin rsky-pds" ]; 18 + cargoInstallFlags = [ "--package rsky-pds --bin rsky-pds" ]; 19 + 20 + meta = with pkgs.lib; { 21 + description = "AT Protocol Personal Data Server (PDS) from rsky"; 22 + homepage = "https://github.com/atproto-nix/nur"; # Placeholder 23 + license = licenses.mit; # Placeholder 24 + maintainers = with maintainers; [ ]; # Placeholder 25 + }; 26 + }; 27 + 28 + relay = craneLib.buildPackage rec { 29 + pname = "rsky-relay"; 30 + version = "0.1.0"; # Placeholder version 31 + src = pkgs.fetchFromGitHub { 32 + owner = "blacksky-algorithms"; 33 + repo = "rsky"; 34 + rev = "main"; # Placeholder 35 + hash = "sha256-nqBe20MCeNrSVxLVxiYc7iCFaBdf5Vf1p/i0D/aS8oY="; 36 + }; 37 + cargoHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; # Placeholder 38 + 39 + cargoBuildFlags = [ "--package rsky-relay --bin rsky-relay" ]; 40 + cargoInstallFlags = [ "--package rsky-relay --bin rsky-relay" ]; 41 + 42 + meta = with pkgs.lib; { 43 + description = "AT Protocol Relay from rsky"; 44 + homepage = "https://github.com/atproto-nix/nur"; 45 + license = licenses.mit; 46 + maintainers = with maintainers; [ ]; 47 + }; 48 + }; 49 + 50 + feedgen = craneLib.buildPackage rec { 51 + pname = "rsky-feedgen"; 52 + version = "0.1.0"; # Placeholder version 53 + src = pkgs.fetchFromGitHub { 54 + owner = "blacksky-algorithms"; 55 + repo = "rsky"; 56 + rev = "main"; # Placeholder 57 + hash = "sha256-nqBe20MCeNrSVxLVxiYc7iCFaBdf5Vf1p/i0D/aS8oY="; 58 + }; 59 + cargoHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; # Placeholder 60 + 61 + cargoBuildFlags = [ "--package rsky-feedgen --bin rsky-feedgen" ]; 62 + cargoInstallFlags = [ "--package rsky-feedgen --bin rsky-feedgen" ]; 63 + 64 + meta = with pkgs.lib; { 65 + description = "AT Protocol Feed Generator from rsky"; 66 + homepage = "https://github.com/atproto-nix/nur"; 67 + license = licenses.mit; 68 + maintainers = with maintainers; [ ]; 69 + }; 70 + }; 71 + 72 + satnav = craneLib.buildPackage rec { 73 + pname = "rsky-satnav"; 74 + version = "0.1.0"; # Placeholder version 75 + src = pkgs.fetchFromGitHub { 76 + owner = "blacksky-algorithms"; 77 + repo = "rsky"; 78 + rev = "main"; # Placeholder 79 + hash = "sha256-nqBe20MCeNrSVxLVxiYc7iCFaBdf5Vf1p/i0D/aS8oY="; 80 + }; 81 + cargoHash = "sha256-0000000000000000000000000000000000000000000000000000000000000000="; # Placeholder, will be updated by Nix 82 + 83 + cargoBuildFlags = [ "--package rsky-satnav --bin rsky-satnav" ]; 84 + cargoInstallFlags = [ "--package rsky-satnav --bin rsky-satnav" ]; 85 + 86 + meta = with pkgs.lib; { 87 + description = "AT Protocol Satnav from rsky"; 88 + homepage = "https://github.com/atproto-nix/nur"; 89 + license = licenses.mit; 90 + maintainers = with maintainers; [ ]; 91 + }; 92 + }; 93 + 94 + firehose = craneLib.buildPackage rec { 95 + pname = "rsky-firehose"; 96 + version = "0.2.1"; # Version from Cargo.toml 97 + src = pkgs.fetchFromGitHub { 98 + owner = "blacksky-algorithms"; 99 + repo = "rsky"; 100 + rev = "main"; # Placeholder 101 + hash = "sha256-nqBe20MCeNrSVxLVxiYc7iCFaBdf5Vf1p/i0D/aS8oY="; 102 + }; 103 + cargoHash = "sha256-0000000000000000000000000000000000000000000000000000000000000000="; # Placeholder 104 + 105 + cargoBuildFlags = [ "--package rsky-firehose --bin rsky-firehose" ]; 106 + cargoInstallFlags = [ "--package rsky-firehose --bin rsky-firehose" ]; 107 + 108 + meta = with pkgs.lib; { 109 + description = "AT Protocol Firehose subscriber from rsky"; 110 + homepage = "https://github.com/atproto-nix/nur"; 111 + license = licenses.mit; 112 + maintainers = with maintainers; [ ]; 113 + }; 114 + }; 115 + 116 + jetstreamSubscriber = craneLib.buildPackage rec { 117 + pname = "rsky-jetstream-subscriber"; 118 + version = "0.1.0"; # Version from Cargo.toml 119 + src = pkgs.fetchFromGitHub { 120 + owner = "blacksky-algorithms"; 121 + repo = "rsky"; 122 + rev = "main"; # Placeholder 123 + hash = "sha256-nqBe20MCeNrSVxLVxiYc7iCFaBdf5Vf1p/i0D/aS8oY="; 124 + }; 125 + cargoHash = "sha256-0000000000000000000000000000000000000000000000000000000000000000="; # Placeholder 126 + 127 + cargoBuildFlags = [ "--package rsky-jetstream-subscriber --bin rsky-jetstream-subscriber" ]; 128 + cargoInstallFlags = [ "--package rsky-jetstream-subscriber --bin rsky-jetstream-subscriber" ]; 129 + 130 + meta = with pkgs.lib; { 131 + description = "AT Protocol Jetstream Subscriber from rsky"; 132 + homepage = "https://github.com/atproto-nix/nur"; 133 + license = licenses.mit; 134 + maintainers = with maintainers; [ ]; 135 + }; 136 + }; 137 + 138 + labeler = craneLib.buildPackage rec { 139 + pname = "rsky-labeler"; 140 + version = "0.1.3"; # Version from Cargo.toml 141 + src = pkgs.fetchFromGitHub { 142 + owner = "blacksky-algorithms"; 143 + repo = "rsky"; 144 + rev = "main"; # Placeholder 145 + hash = "sha256-nqBe20MCeNrSVxLVxiYc7iCFaBdf5Vf1p/i0D/aS8oY="; 146 + }; 147 + cargoHash = "sha256-0000000000000000000000000000000000000000000000000000000000000000="; # Placeholder 148 + 149 + cargoBuildFlags = [ "--package rsky-labeler --bin rsky-labeler" ]; 150 + cargoInstallFlags = [ "--package rsky-labeler --bin rsky-labeler" ]; 151 + 152 + meta = with pkgs.lib; { 153 + description = "AT Protocol Labeler from rsky"; 154 + homepage = "https://github.com/atproto-nix/nur"; 155 + license = licenses.mit; 156 + maintainers = with maintainers; [ ]; 157 + }; 158 + }; 159 + 160 + # community = pkgs.buildYarnPackage rec { 161 + # pname = "blacksky.community"; 162 + # version = "1.109.0"; # Version from package.json 163 + # 164 + # src = pkgs.fetchFromGitHub { 165 + # owner = "blacksky-algorithms"; 166 + # repo = "blacksky.community"; 167 + # # TODO: Update 'rev' to a specific commit hash or release tag for reproducible builds. 168 + # rev = "main"; 169 + # # TODO: Update 'hash' to the correct SHA256 hash of the fetched source. 170 + # # You can obtain the correct hash by setting it to an empty string, running nix-build, 171 + # # and then copying the hash from the error message. 172 + # hash = "sha256-W0mXqED9geNKJSPGJhUdJZ2voMOMDCXX1T4zn3GZKlY="; 173 + # }; 174 + # 175 + # yarnLock = "yarn.lock"; # Specify the yarn.lock file 176 + # 177 + # buildPhase = '' 178 + # yarn build-web 179 + # ''; 180 + # 181 + # installPhase = '' 182 + # mkdir -p $out/share/nginx/html 183 + # cp -r web-build/* $out/share/nginx/html 184 + # ''; 185 + # 186 + # meta = with pkgs.lib; { 187 + # description = "Blacksky Community Web Client"; 188 + # # Placeholder, update with actual homepage if available. 189 + # homepage = "https://github.com/blacksky-algorithms/blacksky.community"; 190 + # # Placeholder, add actual maintainers. 191 + # maintainers = with maintainers; [ ]; 192 + # }; 193 + # }; 194 + }
+80 -8
pkgs/microcosm/default.nix
··· 1 - { stdenv }: 1 + { pkgs, craneLib }: 2 2 3 - stdenv.mkDerivation rec { 4 - name = "example-package-${version}"; 5 - version = "1.0"; 6 - src = ./.; 7 - buildPhase = "echo echo Hello World > example"; 8 - installPhase = "install -Dm755 example $out"; 9 - } 3 + let 4 + src = pkgs.fetchFromGitHub { 5 + owner = "at-microcosm"; 6 + repo = "microcosm-rs"; 7 + rev = "b0a66a102261d0b4e8a90d34cec3421073a7b728"; 8 + sha256 = "sha256-swdAcsjRWnj9abmnrce5LzeKRK+LHm8RubCEIuk+53c="; 9 + }; 10 + 11 + commonEnv = { 12 + LIBCLANG_PATH = pkgs.lib.makeLibraryPath [ pkgs.llvmPackages.libclang.lib ]; 13 + OPENSSL_NO_VENDOR = "1"; 14 + OPENSSL_LIB_DIR = "${pkgs.lib.getLib pkgs.openssl}/lib"; 15 + OPENSSL_INCLUDE_DIR = "${pkgs.lib.getDev pkgs.openssl}/include"; 16 + BINDGEN_EXTRA_CLANG_ARGS = pkgs.lib.concatStringsSep " " [ 17 + "-I${pkgs.llvmPackages.libclang.lib}/lib/clang/${pkgs.lib.versions.major pkgs.llvmPackages.libclang.version}/include" 18 + "-I${pkgs.glibc.dev}" 19 + ]; 20 + ZSTD_SYS_USE_PKG_CONFIG = "1"; 21 + CC = "${pkgs.llvmPackages.clang}/bin/clang"; 22 + CXX = "${pkgs.llvmPackages.clang}/bin/clang++"; 23 + PKG_CONFIG_PATH = "${pkgs.zstd.dev}/lib/pkgconfig:${pkgs.lz4.dev}/lib/pkgconfig"; 24 + }; 25 + 26 + nativeInputs = with pkgs; 27 + [ 28 + pkg-config 29 + perl 30 + ]; 31 + 32 + buildInputs = with pkgs; 33 + [ 34 + zstd 35 + lz4 36 + rocksdb 37 + openssl 38 + sqlite 39 + ]; 40 + cargoArtifacts = craneLib.buildDepsOnly { 41 + inherit src; 42 + pname = "microcosm-rs-deps"; 43 + version = "0.1.0"; 44 + nativeBuildInputs = nativeInputs; 45 + buildInputs = buildInputs; 46 + env = commonEnv; 47 + tarFlags = "--no-same-owner"; 48 + }; 49 + 50 + members = [ 51 + "links" 52 + "constellation" 53 + "jetstream" 54 + "ufos" 55 + "ufos/fuzz" 56 + "spacedust" 57 + "who-am-i" 58 + "slingshot" 59 + "quasar" 60 + "pocket" 61 + "reflector" 62 + ]; 63 + buildPackage = member: 64 + let 65 + packageName = if member == "ufos/fuzz" then "ufos-fuzz" else member; 66 + in 67 + craneLib.buildPackage { 68 + inherit src cargoArtifacts; 69 + pname = packageName; 70 + version = "0.1.0"; 71 + cargoExtraArgs = "--package ${packageName}"; 72 + nativeBuildInputs = nativeInputs; 73 + buildInputs = buildInputs; 74 + tarFlags = "--no-same-owner"; 75 + env = commonEnv; 76 + }; 77 + 78 + packages = pkgs.lib.genAttrs members (member: buildPackage member); 79 + 80 + in 81 + packages
+28
tests/constellation-shell.nix
··· 1 + { pkgs }: 2 + 3 + pkgs.nixosTest { 4 + name = "constellation-shell"; 5 + 6 + nodes.machine = { ... }: 7 + { 8 + imports = [ ../modules/microcosm/constellation.nix ]; 9 + 10 + services.microcosm-constellation = { 11 + enable = true; 12 + jetstream = "us-east-1"; 13 + dataDir = "microcosm-constellation"; 14 + backend = "rocks"; 15 + }; 16 + }; 17 + 18 + # The corrected test script 19 + testScript = '' 20 + start_all() 21 + machine.wait_for_unit("microcosm-constellation.service") 22 + # The line below was removed. wait_for_unit is all you need. 23 + # machine.succeed("systemctl status --wait microcosm-constellation.service") 24 + 25 + # If you want to be extra sure, you can log the status 26 + machine.log(machine.succeed("systemctl status microcosm-constellation.service")) 27 + ''; 28 + }
+5
tests/default.nix
··· 1 + { pkgs }: 2 + { 3 + constellation = import ./constellation.nix { inherit pkgs; }; 4 + constellation-shell = import ./constellation-shell.nix { inherit pkgs; }; 5 + }