AIP Flake (wip)
flake.nix
206 lines 6.6 kB view raw
1{ 2 description = "AIP service"; 3 4 inputs = { 5 nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 6 crane.url = "github:ipetkov/crane"; 7 fenix = { 8 url = "github:nix-community/fenix"; 9 inputs.nixpkgs.follows = "nixpkgs"; 10 inputs.rust-analyzer-src.follows = ""; 11 }; 12 }; 13 14 outputs = { self, nixpkgs, crane, fenix }: 15 let 16 systems = [ "x86_64-linux" ]; 17 forAllSystems = nixpkgs.lib.genAttrs systems; 18 19 mkPackagesForSystem = system: 20 let 21 pkgs = import nixpkgs { 22 inherit system; 23 config = { allowUnfree = true; }; 24 }; 25 26 # Configure crane with stable Rust toolchain 27 craneLib = (crane.mkLib pkgs).overrideToolchain 28 fenix.packages.${system}.stable.toolchain; 29 30 # Project source for crane 31 src = pkgs.lib.cleanSourceWith { 32 src = ./.; 33 filter = path: type: 34 (craneLib.filterCargoSources path type) || 35 (pkgs.lib.hasInfix "/templates/" path) || 36 (pkgs.lib.hasInfix "/static/" path) || 37 (pkgs.lib.hasSuffix "/templates" path) || 38 (pkgs.lib.hasSuffix "/static" path) || 39 (pkgs.lib.hasInfix "/migrations/" path) || 40 (pkgs.lib.hasSuffix "/migrations" path); 41 }; 42 43 commonArgs = { 44 inherit src; 45 version = "0.1.0"; 46 strictDeps = true; 47 pname = "aip"; 48 name = "aip"; 49 buildInputs = with pkgs; [ 50 openssl 51 pkg-config 52 ]; 53 nativeBuildInputs = with pkgs; [ 54 pkg-config 55 openssl.dev 56 # Add sqlx-cli for migrations 57 sqlx-cli 58 ]; 59 60 # Environment variables for OpenSSL 61 OPENSSL_NO_VENDOR = 1; 62 PKG_CONFIG_PATH = "${pkgs.openssl.dev}/lib/pkgconfig"; 63 64 # Pass arguments to cargo build 65 cargoExtraArgs = "--no-default-features --features embed,sqlite --bin aip"; 66 }; 67 68 cargoArtifacts = craneLib.buildDepsOnly commonArgs; 69 70 aip = craneLib.buildPackage (commonArgs // { 71 inherit cargoArtifacts; 72 doCheck = false; 73 CARGO_PROFILE = "release"; 74 }); 75 76 aip-client-management = craneLib.buildPackage (commonArgs // { 77 inherit cargoArtifacts; 78 doCheck = false; 79 CARGO_PROFILE = "release"; 80 cargoExtraArgs = "--no-default-features --features embed,sqlite --bin aip-client-management"; 81 }); 82 83 # Copy migration files 84 migrationFiles = pkgs.stdenv.mkDerivation { 85 name = "aip-migrations"; 86 src = ./migrations; 87 installPhase = '' 88 mkdir -p $out/migrations 89 cp -r * $out/migrations/ 90 ''; 91 }; 92 93 # Copy static files 94 staticFiles = pkgs.stdenv.mkDerivation { 95 name = "aip-static"; 96 src = ./static; 97 installPhase = '' 98 mkdir -p $out/static 99 cp -r * $out/static/ 100 ''; 101 }; 102 103 # Migration runner script 104 migrationRunner = pkgs.writeShellScriptBin "run-migrations" '' 105 set -e 106 107 # Ensure /data directory exists and is writable 108 mkdir -p /data 109 chmod 755 /data 110 111 if [ -z "$DATABASE_URL" ]; then 112 echo "DATABASE_URL environment variable is required" 113 exit 1 114 fi 115 116 # Determine migration source based on database type 117 if [[ "$DATABASE_URL" == sqlite* ]]; then 118 MIGRATION_SOURCE="${migrationFiles}/migrations/sqlite" 119 elif [[ "$DATABASE_URL" == postgres* ]]; then 120 MIGRATION_SOURCE="${migrationFiles}/migrations/postgres" 121 else 122 echo "Unsupported database type in DATABASE_URL: $DATABASE_URL" 123 exit 1 124 fi 125 126 echo "Running migrations from $MIGRATION_SOURCE against $DATABASE_URL" 127 ${pkgs.sqlx-cli}/bin/sqlx database create 128 ${pkgs.sqlx-cli}/bin/sqlx migrate run --source "$MIGRATION_SOURCE" 129 130 # Ensure the database file is writable by all users (SQLite only) 131 if [[ "$DATABASE_URL" == sqlite* ]]; then 132 DB_FILE=$(echo "$DATABASE_URL" | sed 's/sqlite:\/\///') 133 if [ -f "$DB_FILE" ]; then 134 chmod 666 "$DB_FILE" 135 fi 136 fi 137 ''; 138 139 # Docker image for deployment 140 aipImg = pkgs.dockerTools.buildImage { 141 name = "aip"; 142 tag = "latest"; 143 fromImage = pkgs.dockerTools.pullImage { 144 imageName = "alpine"; 145 imageDigest = "sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d"; 146 sha256 = "sha256-Sfb0quuaHgzxA7paz5P51WhdA35to39HtOufceXixz0="; 147 }; 148 copyToRoot = pkgs.buildEnv { 149 name = "image-root"; 150 paths = [ 151 aip 152 aip-client-management 153 migrationRunner 154 staticFiles 155 pkgs.cacert 156 pkgs.sqlx-cli 157 ]; 158 pathsToLink = [ "/bin" "/etc" "/static" ]; 159 }; 160 161 config = { 162 Cmd = [ "/bin/sh" "-c" "if [ ! -f /data/aip.db ]; then /bin/run-migrations; fi && /bin/aip" ]; 163 Env = [ 164 "RUST_BACKTRACE=1" 165 "RUST_LOG=info" 166 "PORT=8080" 167 "HTTP_STATIC_PATH=/static" 168 ]; 169 ExposedPorts = { 170 "8080/tcp" = {}; 171 }; 172 }; 173 }; 174 in 175 { 176 inherit aip aip-client-management aipImg migrationRunner; 177 default = aip; 178 }; 179 in 180 { 181 packages = forAllSystems mkPackagesForSystem; 182 183 devShells = forAllSystems (system: 184 let 185 pkgs = import nixpkgs { inherit system; }; 186 craneLib = (crane.mkLib pkgs).overrideToolchain 187 fenix.packages.${system}.stable.toolchain; 188 in 189 { 190 default = craneLib.devShell { 191 packages = with pkgs; [ 192 nixpkgs-fmt 193 nil 194 dive 195 flyctl 196 sqlite 197 postgresql 198 sqlx-cli 199 ]; 200 201 # Set up environment for development 202 RUST_LOG = "info"; 203 }; 204 }); 205 }; 206}