git.iko.soy/typeable/nixpkgs
on master help sign in
pict-rs: add initial module
commit8346dc04b31bc4ade35bd15a72e6cc40c8ac2f73 authorhappysalada <raphael@megzari.com> dateThu 30 Sep 2021, 21:15 (5 years ago) parent1320843
5 files changed+318
nixos/modules/module-list.nix+1 nixos/modules/services/web-apps/pict-rs.md+88 nixos/modules/services/web-apps/pict-rs.nix+50 nixos/modules/services/web-apps/pict-rs.xml+162 nixos/tests/pict-rs.nix+17
nixos/modules/module-list.nix+1
@@ -991,6 +991,7 @@
991991 ./services/web-apps/nextcloud.nix
992992 ./services/web-apps/nexus.nix
993993 ./services/web-apps/node-red.nix
994+ ./services/web-apps/pict-rs.nix
994995 ./services/web-apps/plantuml-server.nix
995996 ./services/web-apps/plausible.nix
996997 ./services/web-apps/pgpkeyserver-lite.nix
nixos/modules/services/web-apps/pict-rs.mdnew file+88
@@ -0,0 +1,88 @@
1+# Pict-rs {#module-services-pict-rs}
2+
3+pict-rs is a a simple image hosting service.
4+
5+## Quickstart {#module-services-pict-rs-quickstart}
6+
7+the minimum to start pict-rs is
8+
9+```nix
10+services.pict-rs.enable = true;
11+```
12+
13+this will start the http server on port 8080 by default.
14+
15+## Usage {#module-services-pict-rs-usage}
16+
17+pict-rs offers the following endpoints:
18+- `POST /image` for uploading an image. Uploaded content must be valid multipart/form-data with an
19+ image array located within the `images[]` key
20+
21+ This endpoint returns the following JSON structure on success with a 201 Created status
22+ ```json
23+ {
24+ "files": [
25+ {
26+ "delete_token": "JFvFhqJA98",
27+ "file": "lkWZDRvugm.jpg"
28+ },
29+ {
30+ "delete_token": "kAYy9nk2WK",
31+ "file": "8qFS0QooAn.jpg"
32+ },
33+ {
34+ "delete_token": "OxRpM3sf0Y",
35+ "file": "1hJaYfGE01.jpg"
36+ }
37+ ],
38+ "msg": "ok"
39+ }
40+ ```
41+- `GET /image/download?url=...` Download an image from a remote server, returning the same JSON
42+ payload as the `POST` endpoint
43+- `GET /image/original/{file}` for getting a full-resolution image. `file` here is the `file` key from the
44+ `/image` endpoint's JSON
45+- `GET /image/details/original/{file}` for getting the details of a full-resolution image.
46+ The returned JSON is structured like so:
47+ ```json
48+ {
49+ "width": 800,
50+ "height": 537,
51+ "content_type": "image/webp",
52+ "created_at": [
53+ 2020,
54+ 345,
55+ 67376,
56+ 394363487
57+ ]
58+ }
59+ ```
60+- `GET /image/process.{ext}?src={file}&...` get a file with transformations applied.
61+ existing transformations include
62+ - `identity=true`: apply no changes
63+ - `blur={float}`: apply a gaussian blur to the file
64+ - `thumbnail={int}`: produce a thumbnail of the image fitting inside an `{int}` by `{int}`
65+ square using raw pixel sampling
66+ - `resize={int}`: produce a thumbnail of the image fitting inside an `{int}` by `{int}` square
67+ using a Lanczos2 filter. This is slower than sampling but looks a bit better in some cases
68+ - `crop={int-w}x{int-h}`: produce a cropped version of the image with an `{int-w}` by `{int-h}`
69+ aspect ratio. The resulting crop will be centered on the image. Either the width or height
70+ of the image will remain full-size, depending on the image's aspect ratio and the requested
71+ aspect ratio. For example, a 1600x900 image cropped with a 1x1 aspect ratio will become 900x900. A
72+ 1600x1100 image cropped with a 16x9 aspect ratio will become 1600x900.
73+
74+ Supported `ext` file extensions include `png`, `jpg`, and `webp`
75+
76+ An example of usage could be
77+ ```
78+ GET /image/process.jpg?src=asdf.png&thumbnail=256&blur=3.0
79+ ```
80+ which would create a 256x256px JPEG thumbnail and blur it
81+- `GET /image/details/process.{ext}?src={file}&...` for getting the details of a processed image.
82+ The returned JSON is the same format as listed for the full-resolution details endpoint.
83+- `DELETE /image/delete/{delete_token}/{file}` or `GET /image/delete/{delete_token}/{file}` to
84+ delete a file, where `delete_token` and `file` are from the `/image` endpoint's JSON
85+
86+## Missing {#module-services-pict-rs-missing}
87+
88+- Configuring the secure-api-key is not included yet. The envisioned basic use case is consumption on localhost by other services without exposing the service to the internet.
nixos/modules/services/web-apps/pict-rs.nixnew file+50
@@ -0,0 +1,50 @@
1+{ lib, pkgs, config, ... }:
2+with lib;
3+let
4+ cfg = config.services.pict-rs;
5+in
6+{
7+ meta.maintainers = with maintainers; [ happysalada ];
8+ # Don't edit the docbook xml directly, edit the md and generate it:
9+ # `pandoc pict-rs.md -t docbook --top-level-division=chapter --extract-media=media -f markdown+smart > pict-rs.xml`
10+ meta.doc = ./pict-rs.xml;
11+
12+ options.services.pict-rs = {
13+ enable = mkEnableOption "pict-rs server";
14+ dataDir = mkOption {
15+ type = types.path;
16+ default = "/var/lib/pict-rs";
17+ description = ''
18+ The directory where to store the uploaded images.
19+ '';
20+ };
21+ address = mkOption {
22+ type = types.str;
23+ default = "127.0.0.1";
24+ description = ''
25+ The IPv4 address to deploy the service to.
26+ '';
27+ };
28+ port = mkOption {
29+ type = types.port;
30+ default = 8080;
31+ description = ''
32+ The port which to bind the service to.
33+ '';
34+ };
35+ };
36+ config = lib.mkIf cfg.enable {
37+ systemd.services.pict-rs = {
38+ environment = {
39+ PICTRS_PATH = cfg.dataDir;
40+ PICTRS_ADDR = "${cfg.address}:${toString cfg.port}";
41+ };
42+ wantedBy = [ "multi-user.target" ];
43+ serviceConfig = {
44+ DynamicUser = true;
45+ StateDirectory = "pict-rs";
46+ ExecStart = "${pkgs.pict-rs}/bin/pict-rs";
47+ };
48+ };
49+ };
50+}
nixos/modules/services/web-apps/pict-rs.xmlnew file+162
@@ -0,0 +1,162 @@
1+<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-pict-rs">
2+ <title>Pict-rs</title>
3+ <para>
4+ pict-rs is a a simple image hosting service.
5+ </para>
6+ <section xml:id="module-services-pict-rs-quickstart">
7+ <title>Quickstart</title>
8+ <para>
9+ the minimum to start pict-rs is
10+ </para>
11+ <programlisting language="bash">
12+services.pict-rs.enable = true;
13+</programlisting>
14+ <para>
15+ this will start the http server on port 8080 by default.
16+ </para>
17+ </section>
18+ <section xml:id="module-services-pict-rs-usage">
19+ <title>Usage</title>
20+ <para>
21+ pict-rs offers the following endpoints: -
22+ <literal>POST /image</literal> for uploading an image. Uploaded
23+ content must be valid multipart/form-data with an image array
24+ located within the <literal>images[]</literal> key
25+ </para>
26+ <programlisting>
27+This endpoint returns the following JSON structure on success with a 201 Created status
28+```json
29+{
30+ &quot;files&quot;: [
31+ {
32+ &quot;delete_token&quot;: &quot;JFvFhqJA98&quot;,
33+ &quot;file&quot;: &quot;lkWZDRvugm.jpg&quot;
34+ },
35+ {
36+ &quot;delete_token&quot;: &quot;kAYy9nk2WK&quot;,
37+ &quot;file&quot;: &quot;8qFS0QooAn.jpg&quot;
38+ },
39+ {
40+ &quot;delete_token&quot;: &quot;OxRpM3sf0Y&quot;,
41+ &quot;file&quot;: &quot;1hJaYfGE01.jpg&quot;
42+ }
43+ ],
44+ &quot;msg&quot;: &quot;ok&quot;
45+}
46+```
47+</programlisting>
48+ <itemizedlist>
49+ <listitem>
50+ <para>
51+ <literal>GET /image/download?url=...</literal> Download an
52+ image from a remote server, returning the same JSON payload as
53+ the <literal>POST</literal> endpoint
54+ </para>
55+ </listitem>
56+ <listitem>
57+ <para>
58+ <literal>GET /image/original/{file}</literal> for getting a
59+ full-resolution image. <literal>file</literal> here is the
60+ <literal>file</literal> key from the <literal>/image</literal>
61+ endpoint’s JSON
62+ </para>
63+ </listitem>
64+ <listitem>
65+ <para>
66+ <literal>GET /image/details/original/{file}</literal> for
67+ getting the details of a full-resolution image. The returned
68+ JSON is structured like so:
69+ <literal>json { &quot;width&quot;: 800, &quot;height&quot;: 537, &quot;content_type&quot;: &quot;image/webp&quot;, &quot;created_at&quot;: [ 2020, 345, 67376, 394363487 ] }</literal>
70+ </para>
71+ </listitem>
72+ <listitem>
73+ <para>
74+ <literal>GET /image/process.{ext}?src={file}&amp;...</literal>
75+ get a file with transformations applied. existing
76+ transformations include
77+ </para>
78+ <itemizedlist spacing="compact">
79+ <listitem>
80+ <para>
81+ <literal>identity=true</literal>: apply no changes
82+ </para>
83+ </listitem>
84+ <listitem>
85+ <para>
86+ <literal>blur={float}</literal>: apply a gaussian blur to
87+ the file
88+ </para>
89+ </listitem>
90+ <listitem>
91+ <para>
92+ <literal>thumbnail={int}</literal>: produce a thumbnail of
93+ the image fitting inside an <literal>{int}</literal> by
94+ <literal>{int}</literal> square using raw pixel sampling
95+ </para>
96+ </listitem>
97+ <listitem>
98+ <para>
99+ <literal>resize={int}</literal>: produce a thumbnail of
100+ the image fitting inside an <literal>{int}</literal> by
101+ <literal>{int}</literal> square using a Lanczos2 filter.
102+ This is slower than sampling but looks a bit better in
103+ some cases
104+ </para>
105+ </listitem>
106+ <listitem>
107+ <para>
108+ <literal>crop={int-w}x{int-h}</literal>: produce a cropped
109+ version of the image with an <literal>{int-w}</literal> by
110+ <literal>{int-h}</literal> aspect ratio. The resulting
111+ crop will be centered on the image. Either the width or
112+ height of the image will remain full-size, depending on
113+ the image’s aspect ratio and the requested aspect ratio.
114+ For example, a 1600x900 image cropped with a 1x1 aspect
115+ ratio will become 900x900. A 1600x1100 image cropped with
116+ a 16x9 aspect ratio will become 1600x900.
117+ </para>
118+ </listitem>
119+ </itemizedlist>
120+ <para>
121+ Supported <literal>ext</literal> file extensions include
122+ <literal>png</literal>, <literal>jpg</literal>, and
123+ <literal>webp</literal>
124+ </para>
125+ <para>
126+ An example of usage could be
127+ <literal>GET /image/process.jpg?src=asdf.png&amp;thumbnail=256&amp;blur=3.0</literal>
128+ which would create a 256x256px JPEG thumbnail and blur it
129+ </para>
130+ </listitem>
131+ <listitem>
132+ <para>
133+ <literal>GET /image/details/process.{ext}?src={file}&amp;...</literal>
134+ for getting the details of a processed image. The returned
135+ JSON is the same format as listed for the full-resolution
136+ details endpoint.
137+ </para>
138+ </listitem>
139+ <listitem>
140+ <para>
141+ <literal>DELETE /image/delete/{delete_token}/{file}</literal>
142+ or <literal>GET /image/delete/{delete_token}/{file}</literal>
143+ to delete a file, where <literal>delete_token</literal> and
144+ <literal>file</literal> are from the <literal>/image</literal>
145+ endpoint’s JSON
146+ </para>
147+ </listitem>
148+ </itemizedlist>
149+ </section>
150+ <section xml:id="module-services-pict-rs-missing">
151+ <title>Missing</title>
152+ <itemizedlist spacing="compact">
153+ <listitem>
154+ <para>
155+ Configuring the secure-api-key is not included yet. The
156+ envisioned basic use case is consumption on localhost by other
157+ services without exposing the service to the internet.
158+ </para>
159+ </listitem>
160+ </itemizedlist>
161+ </section>
162+</chapter>
nixos/tests/pict-rs.nixnew file+17
@@ -0,0 +1,17 @@
1+import ./make-test-python.nix ({ pkgs, lib, ... }:
2+ {
3+ name = "pict-rs";
4+ meta.maintainers = with lib.maintainers; [ happysalada ];
5+
6+ machine = { ... }: {
7+ environment.systemPackages = with pkgs; [ curl jq ];
8+ services.pict-rs.enable = true;
9+ };
10+
11+ testScript = ''
12+ start_all()
13+
14+ machine.wait_for_unit("pict-rs")
15+ machine.wait_for_open_port("8080")
16+ '';
17+ })