Merge branch 'main' of git.n2.pm:NotNite/u
This commit is contained in:
commit
4add9bcc8d
7 changed files with 383 additions and 8 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -228,6 +228,9 @@ name = "either"
|
||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
|
@ -1087,6 +1090,7 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-pemfile",
|
"rustls-pemfile",
|
||||||
|
"serde",
|
||||||
"sha2",
|
"sha2",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"sqlformat",
|
"sqlformat",
|
||||||
|
@ -1107,9 +1111,12 @@ dependencies = [
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"either",
|
"either",
|
||||||
"heck",
|
"heck",
|
||||||
|
"hex",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"sqlx-rt",
|
"sqlx-rt",
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
[package]
|
[package]
|
||||||
name = "u"
|
name = "u"
|
||||||
|
description = "blazingly-fast super-concurrent webscale file server"
|
||||||
|
authors = ["NotNite <hi@notnite.com>"]
|
||||||
|
license = "MIT"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.69"
|
anyhow = "1.0.69"
|
||||||
async-trait = "0.1.65"
|
async-trait = "0.1.65"
|
||||||
|
@ -14,7 +15,7 @@ hyper = "0.14.24"
|
||||||
mime_guess = "2.0.4"
|
mime_guess = "2.0.4"
|
||||||
nanoid = "0.4.0"
|
nanoid = "0.4.0"
|
||||||
serde = { version = "1.0.152", features = ["derive"] }
|
serde = { version = "1.0.152", features = ["derive"] }
|
||||||
sqlx = { version = "0.6.2", features = ["sqlite", "runtime-tokio-rustls"] }
|
sqlx = { version = "0.6.2", features = ["sqlite", "runtime-tokio-rustls", "offline"] }
|
||||||
tokio = { version = "1.26.0", features = ["full"] }
|
tokio = { version = "1.26.0", features = ["full"] }
|
||||||
tokio-stream = { version = "0.1.12", features = ["net"] }
|
tokio-stream = { version = "0.1.12", features = ["net"] }
|
||||||
tower = "0.4.13"
|
tower = "0.4.13"
|
||||||
|
|
|
@ -35,7 +35,7 @@ requirements:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
export U_API_KEY="..."
|
export U_API_KEY="..."
|
||||||
export U_HOST="https://.../"
|
export U_HOST="https://..."
|
||||||
export U_REVOCATION_KEY_PATH="$HOME/.u_revocation_keys"
|
export U_REVOCATION_KEY_PATH="$HOME/.u_revocation_keys"
|
||||||
|
|
||||||
./upload.sh /path/to/file
|
./upload.sh /path/to/file
|
||||||
|
|
141
flake.lock
Normal file
141
flake.lock
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"crane": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat",
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"rust-overlay": "rust-overlay"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681680516,
|
||||||
|
"narHash": "sha256-EB8Adaeg4zgcYDJn9sR6UMjN/OHdIiMMK19+3LmmXQY=",
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"rev": "54b63c8eae4c50172cb50b612946ff1d2bc1c75c",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-compat": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1673956053,
|
||||||
|
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1678901627,
|
||||||
|
"narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils_2": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681202837,
|
||||||
|
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1682566018,
|
||||||
|
"narHash": "sha256-HPzPRFiy2o/7k7mtnwfM1E6NVZHiFbPdmYCMoIpkHO4=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "8e3b64db39f2aaa14b35ee5376bd6a2e707cadc2",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"crane": "crane",
|
||||||
|
"flake-utils": "flake-utils_2",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-overlay": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": [
|
||||||
|
"crane",
|
||||||
|
"flake-utils"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"crane",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1680488274,
|
||||||
|
"narHash": "sha256-0vYMrZDdokVmPQQXtFpnqA2wEgCCUXf5a3dDuDVshn0=",
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"rev": "7ec2ff598a172c6e8584457167575b3a1a5d80d8",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
129
flake.nix
Normal file
129
flake.nix
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
{
|
||||||
|
description = "blazingly-fast super-concurrent webscale file server";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
|
crane.url = "github:ipetkov/crane";
|
||||||
|
crane.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, crane, flake-utils }:
|
||||||
|
let
|
||||||
|
description = "blazingly-fast super-concurrent webscale file server";
|
||||||
|
src = ./.;
|
||||||
|
packages = flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = nixpkgs.legacyPackages."${system}";
|
||||||
|
craneLib = crane.lib.${system};
|
||||||
|
in rec {
|
||||||
|
packages.u = craneLib.buildPackage {
|
||||||
|
pname = "u";
|
||||||
|
version = "0.1.0";
|
||||||
|
# Don't use cleanCargoSource here, as it removes sqlx-data.json
|
||||||
|
src = src;
|
||||||
|
doCheck = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
apps.u = flake-utils.lib.mkApp {
|
||||||
|
name = "u";
|
||||||
|
drv = packages.u;
|
||||||
|
};
|
||||||
|
|
||||||
|
packages.u-upload = pkgs.stdenv.mkDerivation rec {
|
||||||
|
name = "u-upload";
|
||||||
|
src =
|
||||||
|
(pkgs.writeScriptBin "u-upload" (builtins.readFile ./upload.sh));
|
||||||
|
|
||||||
|
buildInputs = with pkgs; [ curl jq xclip ];
|
||||||
|
nativeBuildInputs = with pkgs; [ makeWrapper ];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cp bin/u-upload $out/bin
|
||||||
|
wrapProgram $out/bin/u-upload \
|
||||||
|
--prefix PATH : ${pkgs.lib.makeBinPath buildInputs}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
devShell = pkgs.mkShell {
|
||||||
|
inputsFrom = [ packages.u ];
|
||||||
|
nativeBuildInputs = with pkgs; [
|
||||||
|
rustc
|
||||||
|
cargo
|
||||||
|
rust-analyzer
|
||||||
|
sqlx-cli
|
||||||
|
packages.u-upload
|
||||||
|
];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
in packages // {
|
||||||
|
nixosModule = { config, lib, pkgs, ... }:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.services.u;
|
||||||
|
pkg = self.packages.${pkgs.system}.u;
|
||||||
|
in {
|
||||||
|
options.services.u = {
|
||||||
|
enable = mkEnableOption description;
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "u";
|
||||||
|
};
|
||||||
|
|
||||||
|
group = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "u";
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
default = 8075;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
systemd.services.u = {
|
||||||
|
description = description;
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
|
||||||
|
preStart = ''
|
||||||
|
cat > /var/lib/u/.env <<EOF
|
||||||
|
DATABASE_URL="sqlite:/var/lib/u/u.db"
|
||||||
|
U_PORT="${toString cfg.port}"
|
||||||
|
U_FILES_DIR="/var/lib/u/files"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Create and migrate the database
|
||||||
|
${pkgs.sqlx-cli}/bin/sqlx database create
|
||||||
|
${pkgs.sqlx-cli}/bin/sqlx migrate run --source "${src}/migrations"
|
||||||
|
'';
|
||||||
|
|
||||||
|
script = "${pkg}/bin/u";
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
User = cfg.user;
|
||||||
|
Group = cfg.group;
|
||||||
|
Restart = "always";
|
||||||
|
WorkingDirectory = "/var/lib/u";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
users = {
|
||||||
|
users = mkIf (cfg.user == "u") {
|
||||||
|
u = {
|
||||||
|
home = "/var/lib/u";
|
||||||
|
createHome = true;
|
||||||
|
group = cfg.group;
|
||||||
|
isSystemUser = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
groups = mkIf (cfg.group == "u") { u = { }; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
97
sqlx-data.json
Normal file
97
sqlx-data.json
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
{
|
||||||
|
"db": "SQLite",
|
||||||
|
"311dd7c05c12408abfbe7dab000687defe924e52d2ca2ed3c7d95bc4a2db039c": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "insert into api_keys (key, admin) values ($1, false)"
|
||||||
|
},
|
||||||
|
"695d9690323bef0cba686448a5053968ebbb5720a7ca5b62a7f4538c972424d2": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "insert into api_keys (key, admin) values ($1, true)"
|
||||||
|
},
|
||||||
|
"8d43fd96f18e00d562d44d710cc0f5bb2ab40f724d5cbcfcbd960ba9450f0a2d": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "select admin from api_keys where admin = true"
|
||||||
|
},
|
||||||
|
"906d2325e07efbaac3e84fd07994afc0b8720fb34baecb314f7e2123a83961dc": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "select admin from api_keys where key = $1"
|
||||||
|
},
|
||||||
|
"c0a48d1ace5682569cfd52d74396193c6b34e463d1a1dfe1e6027f6f94f7befa": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "insert into files (id, revocation_key) values ($1, $2)"
|
||||||
|
},
|
||||||
|
"c450bea1caa31e3fc498d3eeadc25fa27d90ad83be87e89e336f56cdb7adb628": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "revocation_key",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "select revocation_key from files where id = $1"
|
||||||
|
},
|
||||||
|
"d0982a4445b0d5dceb424bfabdc21a88ff2c85042590e1cccd789a4cd7bc735c": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "delete from files where id = $1"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,15 @@
|
||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
set -eux
|
set -eu
|
||||||
|
|
||||||
path=$1
|
path=$1
|
||||||
extension=$(echo "$path" | cut -d'.' -f2)
|
extension=$(echo "$path" | cut -d'.' -f2)
|
||||||
|
|
||||||
data=$(curl -F file=@$path -H "Authorization: $U_API_KEY" "$U_HOST/api/upload")
|
data=$(curl -F file=@"$path" -H "Authorization: $U_API_KEY" "$U_HOST/api/upload")
|
||||||
image_id=$(echo "$data" | jq -r .id)
|
image_id=$(echo "$data" | jq -r .id)
|
||||||
|
|
||||||
image_revocation_key=$(echo "$data" | jq -r .revocation_key)
|
image_revocation_key=$(echo "$data" | jq -r .revocation_key)
|
||||||
echo "$image_id $image_revocation_key" >> $U_REVOCATION_KEY_PATH
|
echo "$image_id $image_revocation_key" >> "$U_REVOCATION_KEY_PATH"
|
||||||
|
|
||||||
image_url="https://u.n2.pm/i/$image_id.$extension"
|
image_url="$U_HOST/i/$image_id.$extension"
|
||||||
echo "$image_url"
|
echo "$image_url"
|
||||||
echo "$image_url" | xclip -selection clipboard
|
echo "$image_url" | xclip -selection clipboard
|
||||||
|
|
Loading…
Reference in a new issue