🗝
summary refs log tree commit diff
diff options
context:
space:
mode:
authormia <mia@mia.jetzt>2024-06-08 22:56:05 -0700
committermia <mia@mia.jetzt>2024-06-08 22:56:05 -0700
commit8cf813ff033bbc98a7dd40db6ac11e2e35c7e997 (patch)
treea451059194cbd4ba90993ebdaced4749448ec4df
downloadasylum-8cf813ff033bbc98a7dd40db6ac11e2e35c7e997.tar.gz
asylum-8cf813ff033bbc98a7dd40db6ac11e2e35c7e997.zip
initial commit
-rw-r--r--.envrc2
-rw-r--r--.gitignore3
-rw-r--r--.vscode/settings.json5
-rwxr-xr-xcgit/css.sh34
-rw-r--r--cgit/header.html1
-rwxr-xr-xcgit/hide.sh11
-rwxr-xr-xcgit/new.sh19
-rw-r--r--cgit/patch.css5
-rw-r--r--cgit/private20
-rw-r--r--cgit/public24
-rw-r--r--cgit/sync.py21
-rwxr-xr-xcgit/unhide.sh11
-rw-r--r--misc/searxng.py28
-rw-r--r--misc/searxng.yml44
-rw-r--r--nginx/fastcgi.conf24
-rw-r--r--nginx/handoff.html26
-rw-r--r--nginx/mime.types1080
-rw-r--r--nginx/nginx.conf115
-rw-r--r--nginx/nginx.js49
-rw-r--r--nginx/sync.py59
-rwxr-xr-xnginx/types.sh32
-rw-r--r--packages/.gitignore9
-rw-r--r--packages/aur.ini8
-rw-r--r--packages/aur.py121
-rw-r--r--packages/cgit-syntect-bat/.gitignore1
-rw-r--r--packages/cgit-syntect-bat/PKGBUILD28
-rw-r--r--packages/cgit-syntect/.gitignore1
-rw-r--r--packages/cgit-syntect/PKGBUILD29
-rw-r--r--packages/dissociate/.gitignore1
-rw-r--r--packages/dissociate/PKGBUILD31
-rw-r--r--packages/dissociate/dissociate.hook9
-rw-r--r--packages/dissociate/dissociate.service11
-rw-r--r--packages/dissociate/dissociate.sysusers1
-rw-r--r--packages/dissociate/dissociate.tmpfiles2
-rw-r--r--packages/init.py42
-rw-r--r--packages/local.py51
-rw-r--r--packages/official.py58
-rw-r--r--packages/packages.inil52
-rw-r--r--packages/searxng/.gitignore1
-rw-r--r--packages/searxng/PKGBUILD50
-rw-r--r--packages/searxng/searxng.hook9
-rw-r--r--packages/searxng/searxng.service18
-rw-r--r--packages/searxng/searxng.socket10
-rw-r--r--packages/searxng/searxng.sysusers1
-rwxr-xr-xpackages/searxng/update.sh15
-rw-r--r--packages/update.py10
46 files changed, 2182 insertions, 0 deletions
diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000..3446535
--- /dev/null
+++ b/.envrc
@@ -0,0 +1,2 @@
+# shellcheck shell=sh
+export PYTHONPATH="$PYTHONPATH:$COMMIA"
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..68f5a2f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+__pycache__/
+/cgit/css
+/nginx/nginx.d.ts
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..79bdd56
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,5 @@
+{
+    "shellcheck.ignorePatterns": {
+        "packages/*/PKGBUILD": true
+    }
+}
\ No newline at end of file
diff --git a/cgit/css.sh b/cgit/css.sh
new file mode 100755
index 0000000..b0fd633
--- /dev/null
+++ b/cgit/css.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+set -e
+
+test -d cgit/css && rm -r cgit/css
+mkdir cgit/css
+
+function compile {
+    local variant=$1
+    local css=$2
+    curl -L "https://github.com/ArmandPhilippot/coldark-bat/raw/master/Coldark-$variant.tmTheme" \
+        | MODE=theme cgit-syntect - cgit/css/$css.css cgit/css/scopes
+    sed -i 's/background-color: .*//' cgit/css/$css.css # we don't actually want that
+}
+
+compile Cold light
+compile Dark dark
+
+curl https://git.kernel.org/cgit-data/cgit.css \
+    | tail -n+2 \
+    | sed 's/font-family: .* monospace/font-family: monospace/' \
+    | sed -n '/Style definition file/q;p' \
+    > cgit/css/kernel.css
+
+{
+    echo '/* adapted from https://git.kernel.org/cgit-data/cgit.css */'
+    cat cgit/css/kernel.css
+    cat cgit/css/light.css
+    echo "@media only all and (prefers-color-scheme: dark) {"
+    cat cgit/css/dark.css
+    echo "}"
+    cat cgit/patch.css
+} | prettier --parser css > cgit/css/style.css
+
+# rm -r cgit/css
diff --git a/cgit/header.html b/cgit/header.html
new file mode 100644
index 0000000..c9f6673
--- /dev/null
+++ b/cgit/header.html
@@ -0,0 +1 @@
+<a href="/priv" id="visibility">%</a>
diff --git a/cgit/hide.sh b/cgit/hide.sh
new file mode 100755
index 0000000..e0b0fba
--- /dev/null
+++ b/cgit/hide.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# shellcheck disable=SC2086
+set -e
+
+if [ -z "$1" ]; then
+	echo missing name
+	exit 1
+fi
+
+set -x
+ssh git@asylum rm $1.git/git-daemon-export-ok
diff --git a/cgit/new.sh b/cgit/new.sh
new file mode 100755
index 0000000..25f11a1
--- /dev/null
+++ b/cgit/new.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# shellcheck disable=SC2086,SC2162
+set -e
+
+if [ -z "$1" ]; then
+	echo missing name
+	exit 1
+fi
+
+read -n1 -p "Make public? " public
+echo
+
+set -x
+ssh git@asylum mkdir $1.git '&&' cd $1.git '&&' git init --bare
+ssh -t git@asylum rm $1.git/description '&&' micro $1.git/description
+
+if [ $public = y ]; then
+	ssh git@asylum touch $1.git/git-daemon-export-ok
+fi
diff --git a/cgit/patch.css b/cgit/patch.css
new file mode 100644
index 0000000..9a28e0d
--- /dev/null
+++ b/cgit/patch.css
@@ -0,0 +1,5 @@
+#visibility {
+    position: absolute;
+    right: 1em;
+    text-decoration: none;
+}
\ No newline at end of file
diff --git a/cgit/private b/cgit/private
new file mode 100644
index 0000000..b2e9f73
--- /dev/null
+++ b/cgit/private
@@ -0,0 +1,20 @@
+# shellcheck disable=all # this isn't a shell file, dingus
+
+about-filter=/usr/bin/cgit-about-filter.sh
+clone-url=git@asylum:$CGIT_REPO_URL
+css=/style.css
+enable-blame=1
+enable-git-config=1
+enable-index-owner=0
+enable-log-filecount=1
+enable-log-linecount=1
+header=/etc/cgit/private-header.html
+logo-link=https://git.causal.agency/cgit-pink/about/
+readme=:README.md
+root-desc=private git repositories
+snapshots=tar.gz zip
+source-filter=/usr/bin/cgit-syntect
+virtual-root=/priv
+
+remove-suffix=1
+scan-path=/srv/git
diff --git a/cgit/public b/cgit/public
new file mode 100644
index 0000000..d6633de
--- /dev/null
+++ b/cgit/public
@@ -0,0 +1,24 @@
+# shellcheck disable=all # this isn't a shell file, dingus
+
+about-filter=/usr/bin/cgit-about-filter.sh
+clone-url=https://$HTTP_HOST/$CGIT_REPO_URL git@asylum:$CGIT_REPO_URL
+css=/style.css
+enable-blame=1
+enable-git-config=1
+enable-index-owner=0
+enable-log-filecount=1
+enable-log-linecount=1
+header=/etc/cgit/public-header.html
+logo-link=https://git.causal.agency/cgit-pink/about/
+readme=:README.md
+root-desc=personal git repositories
+snapshots=tar.gz zip
+source-filter=/usr/bin/cgit-syntect
+virtual-root=/
+
+cache-root=/srv/git/.cache
+cache-size=1M
+
+remove-suffix=1
+strict-export=git-daemon-export-ok
+scan-path=/srv/git
diff --git a/cgit/sync.py b/cgit/sync.py
new file mode 100644
index 0000000..506c811
--- /dev/null
+++ b/cgit/sync.py
@@ -0,0 +1,21 @@
+from commia.prelude import *
+from commia.ssh import scp, ssh_args
+from commia.util import with_written
+
+run_check(
+    [*ssh_args(), "sh", "-c", "cat > /usr/bin/cgit-about-filter.sh"],
+    input=b"#!/bin/sh\nmd2html",  # discard arguments
+)
+run_check([*ssh_args(), "chmod", "+x", "/usr/bin/cgit-about-filter.sh"])
+scp("cgit/public", "asylum:/etc/cgit/public")
+scp("cgit/private", "asylum:/etc/cgit/private")
+if Path("cgit/css").exists():
+    scp("cgit/css/style.css", "asylum:/usr/share/webapps/cgit/style.css")
+    scp("cgit/css/scopes", "asylum:/usr/share/cgit-syntect/scopes")
+
+for sym, vis in [("🗝", "public"), ("⛯", "private")]:
+    with_written(
+        f"<a href=/{'priv' if vis == 'public' else ''} id=visibility>{sym}</a>",
+        lambda path: scp(path, f"asylum:/etc/cgit/{vis}-header.html"),
+    )
+    run([*ssh_args(), "chmod", "+r", f"/etc/cgit/{vis}-header.html"])
diff --git a/cgit/unhide.sh b/cgit/unhide.sh
new file mode 100755
index 0000000..06fda05
--- /dev/null
+++ b/cgit/unhide.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# shellcheck disable=SC2086
+set -e
+
+if [ -z "$1" ]; then
+	echo missing name
+	exit 1
+fi
+
+set -x
+ssh git@asylum touch $1.git/git-daemon-export-ok
diff --git a/misc/searxng.py b/misc/searxng.py
new file mode 100644
index 0000000..db56c21
--- /dev/null
+++ b/misc/searxng.py
@@ -0,0 +1,28 @@
+import random
+import string
+
+from commia.bearer import get_key, has_key, keys, set_key
+from commia.prelude import *
+from commia.ssh import ssh_args, ssh_opt_args, ssh_prewarm
+from commia.util import with_written
+
+ssh_prewarm("asylum", "secrets@bearer")
+
+if not has_key(keys.searxng.secret_key):
+    print("initializing secret key")
+    key = ""
+    for _ in range(64):
+        key += random.choice(string.ascii_letters + string.digits + "-_=+")
+    set_key(keys.searxng.secret_key, key)
+
+secret_key = get_key(keys.searxng.secret_key)
+searxng_conf = Path("misc/searxng.yml").read_text().replace("%SECRET_KEY%", secret_key)
+
+with_written(
+    searxng_conf,
+    lambda path: run_sc(
+        ["scp", *ssh_opt_args(), path, "asylum:/etc/searxng/settings.yml"]
+    ),
+)
+
+run_check(p([*ssh_args(), "systemctl", "restart", "searxng"]))
diff --git a/misc/searxng.yml b/misc/searxng.yml
new file mode 100644
index 0000000..cd3bea0
--- /dev/null
+++ b/misc/searxng.yml
@@ -0,0 +1,44 @@
+general:
+  instance_name: search.mia.jetzt
+
+search:
+  safe_search: 1
+  autocomplete: duckduckgo
+
+server:
+  base_url: https://search.mia.jetzt/
+  secret_key: "%SECRET_KEY%"
+  image_proxy: true
+  method: GET
+
+ui:
+  static_use_hash: true
+
+doi_resolvers:
+  oadoi.org: https://oadoi.org/
+
+default_doi_resolver: oadoi.org
+
+engines:
+  # autocomplete
+  - name: duckduckgo
+    engine: duckduckgo
+    disabled: true
+
+  # general
+  - name: bing
+    engine: bing
+    shortcut: bi
+
+  - name: google
+    engine: google
+    shortcut: go
+
+  # image
+  - name: bing images
+    engine: bing_images
+    shortcut: bii
+
+  - name: google images
+    engine: google_images
+    shortcut: goi
diff --git a/nginx/fastcgi.conf b/nginx/fastcgi.conf
new file mode 100644
index 0000000..92ed248
--- /dev/null
+++ b/nginx/fastcgi.conf
@@ -0,0 +1,24 @@
+fastcgi_param QUERY_STRING $query_string;
+fastcgi_param REQUEST_METHOD $request_method;
+fastcgi_param CONTENT_TYPE $content_type;
+fastcgi_param CONTENT_LENGTH $content_length;
+
+fastcgi_param SCRIPT_NAME $fastcgi_script_name;
+fastcgi_param REQUEST_URI $request_uri;
+fastcgi_param DOCUMENT_URI $document_uri;
+fastcgi_param DOCUMENT_ROOT $document_root;
+fastcgi_param SERVER_PROTOCOL $server_protocol;
+fastcgi_param REQUEST_SCHEME $scheme;
+fastcgi_param HTTPS $https if_not_empty;
+
+fastcgi_param GATEWAY_INTERFACE CGI/1.1;
+fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
+
+fastcgi_param REMOTE_ADDR $remote_addr;
+fastcgi_param REMOTE_PORT $remote_port;
+fastcgi_param SERVER_ADDR $server_addr;
+fastcgi_param SERVER_PORT $server_port;
+fastcgi_param SERVER_NAME $server_name;
+
+fastcgi_param PATH_INFO $uri;
+fastcgi_param HTTP_HOST $server_name;
diff --git a/nginx/handoff.html b/nginx/handoff.html
new file mode 100644
index 0000000..c160580
--- /dev/null
+++ b/nginx/handoff.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html style="align-items: center; background-color: darkcyan; display: flex; height: 100%">
+	<head>
+		<title>Handoff</title>
+		<script>
+			(async () => {
+				const response = await fetch("https://dissociate.mia.jetzt/handoff", { credentials: "include" });
+				if (response.status == 200) {
+					const data = await response.json();
+					if (data.expiresIn < 300) {
+						console.log("token expiring soon, reauthenticating");
+						location = "https://dissociate.mia.jetzt/logout";
+					}
+					await fetch(`/.nginx/cookie?token=${data.token}&max_age=${data.expiresIn - 60}`);
+					location = "/";
+				} else {
+					console.log("not authenticated, redirecting");
+					location = "https://dissociate.mia.jetzt/login";
+				}
+			})()
+		</script>
+	</head>
+	<body style="background-color: whitesmoke; color: black; filter: drop-shadow(0.5em 0.7em); margin: auto; padding: 1em">
+		<p style="font-family: serif; font-size: large; margin: 0">Performing authenticated handoff</p>
+	</body>
+</html>
diff --git a/nginx/mime.types b/nginx/mime.types
new file mode 100644
index 0000000..1e07600
--- /dev/null
+++ b/nginx/mime.types
@@ -0,0 +1,1080 @@
+types {
+    application/A2L a2l;
+    application/AML aml;
+    application/andrew-inset ez;
+    application/ATF atf;
+    application/ATFX atfx;
+    application/ATXML atxml;
+    application/atom+xml atom;
+    application/atomcat+xml atomcat;
+    application/atomdeleted+xml atomdeleted;
+    application/atomsvc+xml atomsvc;
+    application/atsc-dwd+xml dwd;
+    application/atsc-held+xml held;
+    application/atsc-rsat+xml rsat;
+    application/auth-policy+xml apxml;
+    application/automationml-amlx+zip amlx;
+    application/bacnet-xdd+zip xdd;
+    application/calendar+xml xcs;
+    application/cbor cbor;
+    application/cccex c3ex;
+    application/ccmp+xml ccmp;
+    application/ccxml+xml ccxml;
+    application/CDFX+XML cdfx;
+    application/cdmi-capability cdmia;
+    application/cdmi-container cdmic;
+    application/cdmi-domain cdmid;
+    application/cdmi-object cdmio;
+    application/cdmi-queue cdmiq;
+    application/CEA cea;
+    application/cellml+xml cellml cml;
+    application/clr 1clr;
+    application/clue_info+xml clue;
+    application/cms cmsc;
+    application/cpl+xml cpl;
+    application/csrattrs csrattrs;
+    application/cwl cwl;
+    application/cwl+json cwl.json;
+    application/dash+xml mpd;
+    application/dashdelta mpdd;
+    application/davmount+xml davmount;
+    application/DCD dcd;
+    application/dicom dcm;
+    application/DII dii;
+    application/DIT dit;
+    application/dskpp+xml xmls;
+    application/dssc+der dssc;
+    application/dssc+xml xdssc;
+    application/dvcs dvc;
+    application/ecmascript es;
+    application/efi efi;
+    application/emma+xml emma;
+    application/emotionml+xml emotionml;
+    application/epub+zip epub;
+    application/exi exi;
+    application/express exp;
+    application/fastinfoset finf;
+    application/fdt+xml fdt;
+    application/font-tdpfr pfr;
+    application/geo+json geojson;
+    application/geopackage+sqlite3 gpkg;
+    application/gltf-buffer glbin glbuf;
+    application/gml+xml gml;
+    application/gzip gz tgz;
+    application/hyperstudio stk;
+    application/inkml+xml ink inkml;
+    application/ipfix ipfix;
+    application/its+xml its;
+    application/java-archive jar;
+    application/jrd+json jrd;
+    application/json json;
+    application/json-patch+json json-patch;
+    application/ld+json jsonld;
+    application/lgr+xml lgr;
+    application/link-format wlnk;
+    application/lost+xml lostxml;
+    application/lostsync+xml lostsyncxml;
+    application/lpf+zip lpf;
+    application/LXF lxf;
+    application/mac-binhex40 hqx;
+    application/mads+xml mads;
+    application/manifest+json webmanifest;
+    application/marc mrc;
+    application/marcxml+xml mrcx;
+    application/mathematica nb ma mb;
+    application/mathml+xml mml;
+    application/mbox mbox;
+    application/metalink4+xml meta4;
+    application/mets+xml mets;
+    application/MF4 mf4;
+    application/mipc h5;
+    application/mmt-aei+xml maei;
+    application/mmt-usd+xml musd;
+    application/mods+xml mods;
+    application/mp21 m21 mp21;
+    application/msword doc;
+    application/mxf mxf;
+    application/n-quads nq;
+    application/n-triples nt;
+    application/ocsp-request orq;
+    application/ocsp-response ors;
+    application/octet-stream bin lha lzh exe class so dll img iso;
+    application/ODA oda;
+    application/ODX odx;
+    application/oebps-package+xml opf;
+    application/ogg ogx;
+    application/opc-nodeset+xml ;
+    application/oxps oxps;
+    application/p21 p21 stp step stpnc 210 ifc;
+    application/p21+zip stpz;
+    application/p2p-overlay+xml relo;
+    application/pdf pdf;
+    application/PDX pdx;
+    application/pem-certificate-chain pem;
+    application/pgp-encrypted pgp;
+    application/pgp-signature sig;
+    application/pkcs10 p10;
+    application/pkcs12 p12 pfx;
+    application/pkcs7-mime p7m p7c;
+    application/pkcs7-signature p7s;
+    application/pkcs8 p8;
+    application/pkcs8-encrypted p8e;
+    application/pkix-cert cer;
+    application/pkix-crl crl;
+    application/pkix-pkipath pkipath;
+    application/pkixcmp pki;
+    application/pls+xml pls;
+    application/postscript ps eps ai;
+    application/provenance+xml provx;
+    application/prs.cww cw cww;
+    application/prs.hpub+zip hpub;
+    application/prs.nprend rnd rct;
+    application/prs.rdf-xml-crypt rdf-crypt;
+    application/prs.xsf+xml xsf;
+    application/pskc+xml pskcxml;
+    application/rdf+xml rdf;
+    application/route-apd+xml rapd;
+    application/route-s-tsid+xml sls;
+    application/route-usd+xml rusd;
+    application/reginfo+xml rif;
+    application/relax-ng-compact-syntax rnc;
+    application/resource-lists-diff+xml rld;
+    application/resource-lists+xml rl;
+    application/rfc+xml rfcxml;
+    application/rls-services+xml rs;
+    application/rpki-ghostbusters gbr;
+    application/rpki-manifest mft;
+    application/rpki-roa roa;
+    application/rtf rtf;
+    application/sarif-external-properties+json sarif-external-properties sarif-external-properties.json;
+    application/sarif+json sarif sarif.json;
+    application/scim+json scim;
+    application/scvp-cv-request scq;
+    application/scvp-cv-response scs;
+    application/scvp-vp-request spq;
+    application/scvp-vp-response spp;
+    application/sdp sdp;
+    application/senml-etch+cbor senml-etchc;
+    application/senml-etch+json senml-etchj;
+    application/senml+cbor senmlc;
+    application/senml+json senml;
+    application/senml+xml senmlx;
+    application/senml-exi senmle;
+    application/sensml+cbor sensmlc;
+    application/sensml+json sensml;
+    application/sensml+xml sensmlx;
+    application/sensml-exi sensmle;
+    application/sgml-open-catalog soc;
+    application/shf+xml shf;
+    application/sieve siv sieve;
+    application/simple-filter+xml cl;
+    application/smil+xml smil smi sml;
+    application/sparql-query rq;
+    application/spdx+json spdx.json;
+    application/sparql-results+xml srx;
+    application/sql sql;
+    application/srgs gram;
+    application/srgs+xml grxml;
+    application/sru+xml sru;
+    application/ssml+xml ssml;
+    application/stix+json stix;
+    application/swid+cbor coswid;
+    application/swid+xml swidtag;
+    application/tamp-apex-update tau;
+    application/tamp-apex-update-confirm auc;
+    application/tamp-community-update tcu;
+    application/tamp-community-update-confirm	cuc;
+    application/td+json jsontd;
+    application/tamp-error ter;
+    application/tamp-sequence-adjust tsa;
+    application/tamp-sequence-adjust-confirm	sac;
+    application/tamp-update tur;
+    application/tamp-update-confirm tuc;
+    application/tei+xml tei teiCorpus odd;
+    application/thraud+xml tfi;
+    application/timestamp-query tsq;
+    application/timestamp-reply tsr;
+    application/timestamped-data tsd;
+    application/tm+json jsontm tm.json tm.jsonld;
+    application/trig trig;
+    application/ttml+xml ttml;
+    application/urc-grpsheet+xml gsheet;
+    application/urc-ressheet+xml rsheet;
+    application/urc-targetdesc+xml td;
+    application/urc-uisocketdesc+xml uis;
+    application/vnd.1000minds.decision-model+xml	1km;
+    application/vnd.1ob ob;
+    application/vnd.3gpp.5gnas ;
+    application/vnd.3gpp.pic-bw-large plb;
+    application/vnd.3gpp.pic-bw-small psb;
+    application/vnd.3gpp.pic-bw-var pvb;
+    application/vnd.3gpp2.sms sms;
+    application/vnd.3gpp2.tcap tcap;
+    application/vnd.3lightssoftware.imagescal	imgcal;
+    application/vnd.3M.Post-it-Notes pwn;
+    application/vnd.accpac.simply.aso aso;
+    application/vnd.accpac.simply.imp imp;
+    application/vnd.acucobol acu;
+    application/vnd.acucorp atc acutc;
+    application/vnd.adobe.flash.movie swf;
+    application/vnd.adobe.formscentral.fcdt fcdt;
+    application/vnd.adobe.fxp fxp fxpl;
+    application/vnd.adobe.xdp+xml xdp;
+    application/vnd.afpc.modca list3820 listafp afp pseg3820;
+    application/vnd.afpc.modca-overlay ovl;
+    application/vnd.afpc.modca-pagesegment psg;
+    application/vnd.age age;
+    application/vnd.ahead.space ahead;
+    application/vnd.airzip.filesecure.azf azf;
+    application/vnd.airzip.filesecure.azs azs;
+    application/vnd.amazon.mobi8-ebook azw3;
+    application/vnd.americandynamics.acc acc;
+    application/vnd.amiga.ami ami;
+    application/vnd.android.ota ota;
+    application/vnd.anki apkg;
+    application/vnd.anser-web-certificate-issue-initiation	cii;
+    application/vnd.anser-web-funds-transfer-initiation	fti;
+    application/vnd.apache.arrow.file arrow;
+    application/vnd.apache.arrow.stream arrows;
+    application/vnd.apexlang apexland apex axdl;
+    application/vnd.apple.installer+xml dist distz pkg mpkg;
+    application/vnd.apple.keynote keynote;
+    application/vnd.apple.mpegurl m3u8;
+    application/vnd.apple.numbers numbers;
+    application/vnd.apple.pages pages;
+    application/vnd.aristanetworks.swi swi;
+    application/vnd.artisan+json artisan;
+    application/vnd.astraea-software.iota iota;
+    application/vnd.audiograph aep;
+    application/vnd.autopackage package;
+    application/vnd.balsamiq.bmml+xml bmml;
+    application/vnd.banana-accounting ac2;
+    application/vnd.balsamiq.bmpr bmpr;
+    application/vnd.belightsoft.lhzd+zip lhzd;
+    application/vnd.belightsoft.lhzl+zip lhzl;
+    application/vnd.blueice.multipass mpm;
+    application/vnd.bluetooth.ep.oob ep;
+    application/vnd.bluetooth.le.oob le;
+    application/vnd.bmi bmi;
+    application/vnd.businessobjects rep;
+    application/vnd.cendio.thinlinc.clientconf	tlclient;
+    application/vnd.chemdraw+xml cdxml;
+    application/vnd.chess-pgn pgn;
+    application/vnd.chipnuts.karaoke-mmd mmd;
+    application/vnd.cinderella cdy;
+    application/vnd.citationstyles.style+xml	csl;
+    application/vnd.claymore cla;
+    application/vnd.cloanto.rp9 rp9;
+    application/vnd.clonk.c4group c4g c4d c4f c4p c4u;
+    application/vnd.cluetrust.cartomobile-config	c11amc;
+    application/vnd.cluetrust.cartomobile-config-pkg	c11amz;
+    application/vnd.coffeescript coffee;
+    application/vnd.collabio.xodocuments.document	xodt;
+    application/vnd.collabio.xodocuments.document-template	xott;
+    application/vnd.collabio.xodocuments.presentation	xodp;
+    application/vnd.collabio.xodocuments.presentation-template	xotp;
+    application/vnd.collabio.xodocuments.spreadsheet	xods;
+    application/vnd.collabio.xodocuments.spreadsheet-template	xots;
+    application/vnd.comicbook-rar cbr;
+    application/vnd.comicbook+zip cbz;
+    application/vnd.commerce-battelle	ica icf icd ic0 ic1 ic2 ic3 ic4 ic5 ic6 ic7 ic8;
+    application/vnd.commonspace csp cst;
+    application/vnd.contact.cmsg cdbcmsg;
+    application/vnd.coreos.ignition+json ign ignition;
+    application/vnd.cosmocaller cmc;
+    application/vnd.crick.clicker clkx;
+    application/vnd.crick.clicker.keyboard clkk;
+    application/vnd.crick.clicker.palette clkp;
+    application/vnd.crick.clicker.template clkt;
+    application/vnd.crick.clicker.wordbank clkw;
+    application/vnd.criticaltools.wbs+xml wbs;
+    application/vnd.crypto-shade-file ssvc;
+    application/vnd.cryptomator.encrypted c9r c9s;
+    application/vnd.cryptomator.vault cryptomator;
+    application/vnd.ctc-posml pml;
+    application/vnd.cups-ppd ppd;
+    application/vnd.curl curl;
+    application/vnd.dart dart;
+    application/vnd.data-vision.rdz rdz;
+    application/vnd.datalog dl;
+    application/vnd.dbf dbf;
+    application/vnd.debian.binary-package deb udeb;
+    application/vnd.dece.data uvf uvvf uvd uvvd;
+    application/vnd.dece.ttml+xml uvt uvvt;
+    application/vnd.dece.unspecified uvx uvvx;
+    application/vnd.dece.zip uvz uvvz;
+    application/vnd.denovo.fcselayout-link fe_launch;
+    application/vnd.desmume.movie dsm;
+    application/vnd.dna dna;
+    application/vnd.document+json docjson;
+    application/vnd.doremir.scorecloud-binary-document	scld;
+    application/vnd.dpgraph dpg mwc dpgraph;
+    application/vnd.dreamfactory dfac;
+    application/vnd.dtg.local.flash fla;
+    application/vnd.dvb.ait ait;
+    application/vnd.dvb.service svc;
+    application/vnd.dynageo geo;
+    application/vnd.dzr dzr;
+    application/vnd.ecowin.chart mag;
+    application/vnd.eln+zip eln;
+    application/vnd.enliven nml;
+    application/vnd.epson.esf esf;
+    application/vnd.epson.msf msf;
+    application/vnd.epson.quickanime qam;
+    application/vnd.epson.salt slt;
+    application/vnd.epson.ssf ssf;
+    application/vnd.ericsson.quickcall qcall qca;
+    application/vnd.espass-espass+zip espass;
+    application/vnd.eszigno3+xml es3 et3;
+    application/vnd.etsi.asic-e+zip asice sce;
+    application/vnd.etsi.asic-s+zip asics;
+    application/vnd.etsi.timestamp-token tst;
+    application/vnd.eu.kasparian.car+json carjson;
+    application/vnd.exstream-empower+zip mpw;
+    application/vnd.exstream-package pub;
+    application/vnd.evolv.ecig.profile ecigprofile;
+    application/vnd.evolv.ecig.settings ecig;
+    application/vnd.evolv.ecig.theme ecigtheme;
+    application/vnd.ezpix-album ez2;
+    application/vnd.ezpix-package ez3;
+    application/vnd.fastcopy-disk-image dim;
+    application/vnd.familysearch.gedcom+zip gdz;
+    application/vnd.fdf fdf;
+    application/vnd.fdsn.mseed msd mseed;
+    application/vnd.fdsn.seed seed dataless;
+    application/vnd.ficlab.flb+zip flb;
+    application/vnd.filmit.zfc zfc;
+    application/vnd.FloGraphIt gph;
+    application/vnd.fluxtime.clip ftc;
+    application/vnd.font-fontforge-sfd sfd;
+    application/vnd.framemaker fm;
+    application/vnd.frogans.fnc fnc;
+    application/vnd.frogans.ltf ltf;
+    application/vnd.fsc.weblaunch fsc;
+    application/vnd.fujitsu.oasys oas;
+    application/vnd.fujitsu.oasys2 oa2;
+    application/vnd.fujitsu.oasys3 oa3;
+    application/vnd.fujitsu.oasysgp fg5;
+    application/vnd.fujitsu.oasysprs bh2;
+    application/vnd.fujixerox.ddd ddd;
+    application/vnd.fujixerox.docuworks xdw;
+    application/vnd.fujixerox.docuworks.binder xbd;
+    application/vnd.fujixerox.docuworks.container xct;
+    application/vnd.fuzzysheet fzs;
+    application/vnd.genomatix.tuxedo txd;
+    application/vnd.genozip genozip;
+    application/vnd.gentoo.ebuild ebuild;
+    application/vnd.gentoo.eclass eclass;
+    application/vnd.gentoo.gpkg gpkg.tar;
+    application/vnd.gentoo.xpak tbz2 xpak;
+    application/vnd.geocube+xml g3 g³;
+    application/vnd.geogebra.file ggb;
+    application/vnd.geogebra.slides ggs;
+    application/vnd.geogebra.tool ggt;
+    application/vnd.geometry-explorer gex gre;
+    application/vnd.geonext gxt;
+    application/vnd.geoplan g2w;
+    application/vnd.geospace g3w;
+    application/vnd.gmx gmx;
+    application/vnd.google-earth.kml+xml kml;
+    application/vnd.google-earth.kmz kmz;
+    application/vnd.grafeq gqf gqs;
+    application/vnd.groove-account gac;
+    application/vnd.groove-help ghf;
+    application/vnd.groove-identity-message gim;
+    application/vnd.groove-injector grv;
+    application/vnd.groove-tool-message gtm;
+    application/vnd.groove-tool-template tpl;
+    application/vnd.groove-vcard vcg;
+    application/vnd.hal+xml hal;
+    application/vnd.HandHeld-Entertainment+xml	zmm;
+    application/vnd.hbci hbci hbc kom upa pkd bpd;
+    application/vnd.hdt hdt;
+    application/vnd.hhe.lesson-player les;
+    application/vnd.hp-HPGL hpgl;
+    application/vnd.hp-hpid hpi hpid;
+    application/vnd.hp-hps hps;
+    application/vnd.hp-jlyt jlt;
+    application/vnd.hp-PCL pcl;
+    application/vnd.hsl hsl;
+    application/vnd.hydrostatix.sof-data sfd-hdstx;
+    application/vnd.hzn-3d-crossword x3d;
+    application/vnd.ibm.electronic-media emm;
+    application/vnd.ibm.MiniPay mpy;
+    application/vnd.ibm.rights-management irm;
+    application/vnd.ibm.secure-container sc;
+    application/vnd.iccprofile icc icm;
+    application/vnd.ieee.1905 1905.1;
+    application/vnd.igloader igl;
+    application/vnd.imagemeter.folder+zip imf;
+    application/vnd.imagemeter.image+zip imi;
+    application/vnd.immervision-ivp ivp;
+    application/vnd.immervision-ivu ivu;
+    application/vnd.ims.imsccv1p1 imscc;
+    application/vnd.insors.igm igm;
+    application/vnd.intercon.formnet xpw xpx;
+    application/vnd.intergeo i2g;
+    application/vnd.intu.qbo qbo;
+    application/vnd.intu.qfx qfx;
+    application/vnd.ipld.car car;
+    application/vnd.ipunplugged.rcprofile rcprofile;
+    application/vnd.irepository.package+xml irp;
+    application/vnd.is-xpr xpr;
+    application/vnd.isac.fcs fcs;
+    application/vnd.jam jam;
+    application/vnd.jcp.javame.midlet-rms rms;
+    application/vnd.jisp jisp;
+    application/vnd.joost.joda-archive joda;
+    application/vnd.kahootz ktz ktr;
+    application/vnd.kde.karbon karbon;
+    application/vnd.kde.kchart chrt;
+    application/vnd.kde.kformula kfo;
+    application/vnd.kde.kivio flw;
+    application/vnd.kde.kontour kon;
+    application/vnd.kde.kpresenter kpr kpt;
+    application/vnd.kde.kspread ksp;
+    application/vnd.kde.kword kwd kwt;
+    application/vnd.kenameaapp htke;
+    application/vnd.kidspiration kia;
+    application/vnd.Kinar kne knp sdf;
+    application/vnd.koan skp skd skm skt;
+    application/vnd.kodak-descriptor sse;
+    application/vnd.las las;
+    application/vnd.las.las+json lasjson;
+    application/vnd.las.las+xml lasxml;
+    application/vnd.llamagraphics.life-balance.desktop	lbd;
+    application/vnd.llamagraphics.life-balance.exchange+xml	lbe;
+    application/vnd.logipipe.circuit+zip lcs lca;
+    application/vnd.loom loom;
+    application/vnd.lotus-1-2-3 123 wk4 wk3 wk1;
+    application/vnd.lotus-approach apr vew;
+    application/vnd.lotus-freelance prz pre;
+    application/vnd.lotus-notes nsf ntf ndl ns4 ns3 ns2 nsh nsg;
+    application/vnd.lotus-organizer or3 or2 org;
+    application/vnd.lotus-screencam scm;
+    application/vnd.lotus-wordpro lwp sam;
+    application/vnd.macports.portpkg portpkg;
+    application/vnd.mapbox-vector-tile mvt;
+    application/vnd.marlin.drm.mdcf mdc;
+    application/vnd.maxar.archive.3tz+zip 3tz;
+    application/vnd.maxmind.maxmind-db mmdb;
+    application/vnd.mcd mcd;
+    application/vnd.mdl mdl;
+    application/vnd.mdl-mbsdf mbsdf;
+    application/vnd.medcalcdata mc1;
+    application/vnd.mediastation.cdkey cdkey;
+    application/vnd.medicalholodeck.recordxr rxr;
+    application/vnd.MFER mwf;
+    application/vnd.mfmp mfm;
+    application/vnd.micrografx.flo flo;
+    application/vnd.micrografx.igx igx;
+    application/vnd.mif mif;
+    application/vnd.Mobius.DAF daf;
+    application/vnd.Mobius.DIS dis;
+    application/vnd.Mobius.MBK mbk;
+    application/vnd.Mobius.MQY mqy;
+    application/vnd.Mobius.MSL msl;
+    application/vnd.Mobius.PLC plc;
+    application/vnd.Mobius.TXF txf;
+    application/vnd.modl modl;
+    application/vnd.mophun.application mpn;
+    application/vnd.mophun.certificate mpc;
+    application/vnd.mozilla.xul+xml xul;
+    application/vnd.ms-3mfdocument 3mf;
+    application/vnd.ms-artgalry cil;
+    application/vnd.ms-asf asf;
+    application/vnd.ms-cab-compressed cab;
+    application/vnd.ms-excel xls xlm xla xlc xlt xlw;
+    application/vnd.ms-excel.template.macroEnabled.12	xltm;
+    application/vnd.ms-excel.addin.macroEnabled.12	xlam;
+    application/vnd.ms-excel.sheet.binary.macroEnabled.12	xlsb;
+    application/vnd.ms-excel.sheet.macroEnabled.12	xlsm;
+    application/vnd.ms-fontobject eot;
+    application/vnd.ms-htmlhelp chm;
+    application/vnd.ms-ims ims;
+    application/vnd.ms-lrm lrm;
+    application/vnd.ms-officetheme thmx;
+    application/vnd.ms-powerpoint ppt pps pot;
+    application/vnd.ms-powerpoint.addin.macroEnabled.12	ppam;
+    application/vnd.ms-powerpoint.presentation.macroEnabled.12	pptm;
+    application/vnd.ms-powerpoint.slide.macroEnabled.12	sldm;
+    application/vnd.ms-powerpoint.slideshow.macroEnabled.12	ppsm;
+    application/vnd.ms-powerpoint.template.macroEnabled.12	potm;
+    application/vnd.ms-project mpp mpt;
+    application/vnd.ms-tnef tnef tnf;
+    application/vnd.ms-word.document.macroEnabled.12	docm;
+    application/vnd.ms-word.template.macroEnabled.12	dotm;
+    application/vnd.ms-works wcm wdb wks wps;
+    application/vnd.ms-wpl wpl;
+    application/vnd.ms-xpsdocument xps;
+    application/vnd.msa-disk-image msa;
+    application/vnd.mseq mseq;
+    application/vnd.multiad.creator crtr;
+    application/vnd.multiad.creator.cif cif;
+    application/vnd.musician mus;
+    application/vnd.muvee.style msty;
+    application/vnd.mynfc taglet;
+    application/vnd.nebumind.line nebul line;
+    application/vnd.nervana entity request bkm kcm;
+    application/vnd.nimn nimn;
+    application/vnd.nitf nitf;
+    application/vnd.neurolanguage.nlu nlu;
+    application/vnd.nintendo.nitro.rom nds;
+    application/vnd.nintendo.snes.rom sfc smc;
+    application/vnd.noblenet-directory nnd;
+    application/vnd.noblenet-sealer nns;
+    application/vnd.noblenet-web nnw;
+    application/vnd.nokia.n-gage.ac+xml ac;
+    application/vnd.nokia.n-gage.data ngdat;
+    application/vnd.nokia.n-gage.symbian.install	n-gage;
+    application/vnd.nokia.radio-preset rpst;
+    application/vnd.nokia.radio-presets rpss;
+    application/vnd.novadigm.EDM edm;
+    application/vnd.novadigm.EDX edx;
+    application/vnd.novadigm.EXT ext;
+    application/vnd.oasis.opendocument.base odb;
+    application/vnd.oasis.opendocument.chart odc;
+    application/vnd.oasis.opendocument.chart-template otc;
+    application/vnd.oasis.opendocument.formula odf;
+    application/vnd.oasis.opendocument.graphics odg;
+    application/vnd.oasis.opendocument.graphics-template otg;
+    application/vnd.oasis.opendocument.image odi;
+    application/vnd.oasis.opendocument.image-template oti;
+    application/vnd.oasis.opendocument.presentation odp;
+    application/vnd.oasis.opendocument.presentation-template	otp;
+    application/vnd.oasis.opendocument.spreadsheet ods;
+    application/vnd.oasis.opendocument.spreadsheet-template ots;
+    application/vnd.oasis.opendocument.text odt;
+    application/vnd.oasis.opendocument.text-master odm;
+    application/vnd.oasis.opendocument.text-master-template otm;
+    application/vnd.oasis.opendocument.text-template ott;
+    application/vnd.oasis.opendocument.text-web oth;
+    application/vnd.olpc-sugar xo;
+    application/vnd.oma.dd2+xml dd2;
+    application/vnd.onepager tam;
+    application/vnd.onepagertamp tamp;
+    application/vnd.onepagertamx tamx;
+    application/vnd.onepagertat tat;
+    application/vnd.onepagertatp tatp;
+    application/vnd.onepagertatx tatx;
+    application/vnd.openblox.game+xml obgx;
+    application/vnd.openblox.game-binary obg;
+    application/vnd.openeye.oeb oeb;
+    application/vnd.openofficeorg.extension oxt;
+    application/vnd.openstreetmap.data+xml osm;
+    application/vnd.openxmlformats-officedocument.presentationml.presentation pptx;
+    application/vnd.openxmlformats-officedocument.presentationml.slide	sldx;
+    application/vnd.openxmlformats-officedocument.presentationml.slideshow	ppsx;
+    application/vnd.openxmlformats-officedocument.presentationml.template	potx;
+    application/vnd.openxmlformats-officedocument.spreadsheetml.sheet	xlsx;
+    application/vnd.openxmlformats-officedocument.spreadsheetml.template	xltx;
+    application/vnd.openxmlformats-officedocument.wordprocessingml.document	docx;
+    application/vnd.openxmlformats-officedocument.wordprocessingml.template	dotx;
+    application/vnd.osa.netdeploy ndc;
+    application/vnd.osgeo.mapguide.package mgp;
+    application/vnd.osgi.dp dp;
+    application/vnd.osgi.subsystem esa;
+    application/vnd.oxli.countgraph oxlicg;
+    application/vnd.palm prc pdb pqa oprc;
+    application/vnd.panoply plp;
+    application/vnd.patentdive dive;
+    application/vnd.pawaafile paw;
+    application/vnd.pg.format str;
+    application/vnd.pg.osasli ei6;
+    application/vnd.piaccess.application-licence	pil;
+    application/vnd.picsel efif;
+    application/vnd.pmi.widget wg;
+    application/vnd.pocketlearn plf;
+    application/vnd.powerbuilder6 pbd;
+    application/vnd.preminet preminet;
+    application/vnd.previewsystems.box box vbox;
+    application/vnd.proteus.magazine mgz;
+    application/vnd.psfs psfs;
+    application/vnd.publishare-delta-tree qps;
+    application/vnd.pvi.ptid1 ptid;
+    application/vnd.qualcomm.brew-app-res bar;
+    application/vnd.Quark.QuarkXPress qxd qxt qwd qwt qxl qxb;
+    application/vnd.quobject-quoxdocument quox quiz;
+    application/vnd.rainstor.data tree;
+    application/vnd.rar rar;
+    application/vnd.realvnc.bed bed;
+    application/vnd.recordare.musicxml mxl;
+    application/vnd.resilient.logic rlm reload;
+    application/vnd.rig.cryptonote cryptonote;
+    application/vnd.route66.link66+xml link66;
+    application/vnd.sailingtracker.track st;
+    application/vnd.sar SAR;
+    application/vnd.scribus scd sla slaz;
+    application/vnd.sealed.3df s3df;
+    application/vnd.sealed.csf scsf;
+    application/vnd.sealed.doc sdoc sdo s1w;
+    application/vnd.sealed.eml seml sem;
+    application/vnd.sealed.mht smht smh;
+    application/vnd.sealed.ppt sppt s1p;
+    application/vnd.sealed.tiff stif;
+    application/vnd.sealed.xls sxls sxl s1e;
+    application/vnd.sealedmedia.softseal.html	stml s1h;
+    application/vnd.sealedmedia.softseal.pdf	spdf spd s1a;
+    application/vnd.seemail see;
+    application/vnd.sema sema;
+    application/vnd.semd semd;
+    application/vnd.semf semf;
+    application/vnd.shade-save-file ssv;
+    application/vnd.shana.informed.formdata ifm;
+    application/vnd.shana.informed.formtemplate	itp;
+    application/vnd.shana.informed.interchange	iif;
+    application/vnd.shana.informed.package ipk;
+    application/vnd.shp shp;
+    application/vnd.shx shx;
+    application/vnd.sigrok.session sr;
+    application/vnd.SimTech-MindMapper twd twds;
+    application/vnd.smaf mmf;
+    application/vnd.smart.notebook notebook;
+    application/vnd.smart.teacher teacher;
+    application/vnd.smintio.portals.archive sipa;
+    application/vnd.snesdev-page-table ptrom pt;
+    application/vnd.software602.filler.form+xml	fo;
+    application/vnd.software602.filler.form-xml-zip	zfo;
+    application/vnd.solent.sdkm+xml sdkm sdkd;
+    application/vnd.spotfire.dxp dxp;
+    application/vnd.spotfire.sfs sfs;
+    application/vnd.sqlite3 sqlite sqlite3;
+    application/vnd.stepmania.package smzip;
+    application/vnd.stepmania.stepchart sm;
+    application/vnd.sun.wadl+xml wadl;
+    application/vnd.sus-calendar sus susp;
+    application/vnd.sybyl.mol2 ml2 mol2 sy2;
+    application/vnd.sycle+xml scl;
+    application/vnd.syft+json syft.json;
+    application/vnd.syncml+xml xsm;
+    application/vnd.syncml.dm+wbxml bdm;
+    application/vnd.syncml.dm+xml xdm;
+    application/vnd.syncml.dmddf+xml ddf;
+    application/vnd.tao.intent-module-archive	tao;
+    application/vnd.tcpdump.pcap pcap cap dmp;
+    application/vnd.theqvd qvd;
+    application/vnd.think-cell.ppttc+json ppttc;
+    application/vnd.tml vfr viaframe;
+    application/vnd.tmobile-livetv tmo;
+    application/vnd.trid.tpt tpt;
+    application/vnd.triscape.mxs mxs;
+    application/vnd.trueapp tra;
+    application/vnd.ufdl ufdl ufd frm;
+    application/vnd.uiq.theme utz;
+    application/vnd.umajin umj;
+    application/vnd.unity unityweb;
+    application/vnd.uoml+xml uoml uo;
+    application/vnd.uri-map urim urimap;
+    application/vnd.valve.source.material vmt;
+    application/vnd.vcx vcx;
+    application/vnd.vd-study mxi study-inter model-inter;
+    application/vnd.vectorworks vwx;
+    application/vnd.veritone.aion+json aion vtnstd;
+    application/vnd.veryant.thin istc isws;
+    application/vnd.ves.encrypted VES;
+    application/vnd.vidsoft.vidconference vsc;
+    application/vnd.visio vsd vst vsw vss;
+    application/vnd.visionary vis;
+    application/vnd.vsf vsf;
+    application/vnd.wap.sic sic;
+    application/vnd.wap.slc slc;
+    application/vnd.wap.wbxml wbxml;
+    application/vnd.wap.wmlc wmlc;
+    application/vnd.wap.wmlscriptc wmlsc;
+    application/vnd.wasmflow.wafl wafl;
+    application/vnd.webturbo wtb;
+    application/vnd.wfa.p2p p2p;
+    application/vnd.wfa.wsc wsc;
+    application/vnd.wmc wmc;
+    application/vnd.wolfram.mathematica.package	m;
+    application/vnd.wolfram.player nbp;
+    application/vnd.wordperfect wpd;
+    application/vnd.wqd wqd;
+    application/vnd.wt.stf stf;
+    application/vnd.wv.csp+wbxml wv;
+    application/vnd.xara xar;
+    application/vnd.xfdl xfdl xfd;
+    application/vnd.xmpie.cpkg cpkg;
+    application/vnd.xmpie.dpkg dpkg;
+    application/vnd.xmpie.ppkg ppkg;
+    application/vnd.xmpie.xlim xlim;
+    application/vnd.yamaha.hv-dic hvd;
+    application/vnd.yamaha.hv-script hvs;
+    application/vnd.yamaha.hv-voice hvp;
+    application/vnd.yamaha.openscoreformat osf;
+    application/vnd.yamaha.smaf-audio saf;
+    application/vnd.yamaha.smaf-phrase spf;
+    application/vnd.yaoweme yme;
+    application/vnd.yellowriver-custom-menu cmp;
+    application/vnd.zul zir zirz;
+    application/vnd.zzazz.deck+xml zaz;
+    application/voicexml+xml vxml;
+    application/voucher-cms+json vcj;
+    application/wasm wasm;
+    application/watcherinfo+xml wif;
+    application/widget wgt;
+    application/wsdl+xml wsdl;
+    application/wspolicy+xml wspolicy;
+    application/xcap-att+xml xav;
+    application/xcap-caps+xml xca;
+    application/xcap-diff+xml xdf;
+    application/xcap-el+xml xel;
+    application/xcap-error+xml xer;
+    application/xcap-ns+xml xns;
+    application/xfdf xfdf;
+    application/xhtml+xml xhtml xhtm xht;
+    application/xliff+xml xlf;
+    application/xml-dtd dtd;
+    application/xop+xml xop;
+    application/xslt+xml xsl xslt;
+    application/xv+xml mxml xhvml xvml xvm;
+    application/yang yang;
+    application/yin+xml yin;
+    application/zip zip;
+    application/zstd zst;
+    audio/32kadpcm 726;
+    audio/aac adts aac ass;
+    audio/ac3 ac3;
+    audio/AMR amr;
+    audio/AMR-WB awb;
+    audio/asc acn;
+    audio/ATRAC-ADVANCED-LOSSLESS aal;
+    audio/ATRAC-X atx;
+    audio/ATRAC3 at3 aa3 omg;
+    audio/basic au snd;
+    audio/dls dls;
+    audio/EVRC evc;
+    audio/EVRCB evb;
+    audio/EVRCNW enw;
+    audio/EVRCWB evw;
+    audio/iLBC lbc;
+    audio/L16 l16;
+    audio/mhas mhas;
+    audio/mobile-xmf mxmf;
+    audio/mp4 m4a;
+    audio/mpeg mp3 mpga mp1 mp2;
+    audio/ogg oga ogg opus spx;
+    audio/prs.sid sid psid;
+    audio/QCELP qcp;
+    audio/SMV smv;
+    audio/sofa sofa;
+    audio/usac loas xhe;
+    audio/vnd.audiokoz koz;
+    audio/vnd.dece.audio uva uvva;
+    audio/vnd.digital-winds eol;
+    audio/vnd.dolby.mlp mlp;
+    audio/vnd.dts dts;
+    audio/vnd.dts.hd dtshd;
+    audio/vnd.everad.plj plj;
+    audio/vnd.lucent.voice lvp;
+    audio/vnd.ms-playready.media.pya pya;
+    audio/vnd.nortel.vbk vbk;
+    audio/vnd.nuera.ecelp4800 ecelp4800;
+    audio/vnd.nuera.ecelp7470 ecelp7470;
+    audio/vnd.nuera.ecelp9600 ecelp9600;
+    audio/vnd.presonus.multitrack multitrack;
+    audio/vnd.rip rip;
+    audio/vnd.sealedmedia.softseal.mpeg smp3 smp s1m;
+    font/collection ttc;
+    font/otf otf;
+    font/ttf ttf;
+    font/woff woff;
+    font/woff2 woff2;
+    image/aces exr;
+    image/avci avci;
+    image/avcs avcs;
+    image/avif avif hif;
+    image/bmp bmp dib;
+    image/cgm cgm;
+    image/dicom-rle drle;
+    image/dpx dpx;
+    image/emf emf;
+    image/fits fits fit fts;
+    image/heic heic;
+    image/heic-sequence heics;
+    image/heif heif;
+    image/heif-sequence heifs;
+    image/hej2k hej2;
+    image/hsj2 hsj2;
+    image/gif gif;
+    image/ief ief;
+    image/jls jls;
+    image/jp2 jp2 jpg2;
+    image/jph jph;
+    image/jphc jhc;
+    image/jpeg jpg jpeg jpe jfif;
+    image/jpm jpm jpgm;
+    image/jpx jpx jpf;
+    image/jxl jxl;
+    image/jxr jxr;
+    image/jxrA jxra;
+    image/jxrS jxrs;
+    image/jxs jxs;
+    image/jxsc jxsc;
+    image/jxsi jxsi;
+    image/jxss jxss;
+    image/ktx ktx;
+    image/ktx2 ktx2;
+    image/png png;
+    image/prs.btif btif btf;
+    image/prs.pti pti;
+    image/svg+xml svg svgz;
+    image/t38 t38;
+    image/tiff tiff tif;
+    image/tiff-fx tfx;
+    image/vnd.adobe.photoshop psd;
+    image/vnd.airzip.accelerator.azv azv;
+    image/vnd.dece.graphic uvi uvvi uvg uvvg;
+    image/vnd.djvu djvu djv;
+    image/vnd.dwg dwg;
+    image/vnd.dxf dxf;
+    image/vnd.fastbidsheet fbs;
+    image/vnd.fpx fpx;
+    image/vnd.fst fst;
+    image/vnd.fujixerox.edmics-mmr mmr;
+    image/vnd.fujixerox.edmics-rlc rlc;
+    image/vnd.globalgraphics.pgb pgb;
+    image/vnd.microsoft.icon ico;
+    image/vnd.mozilla.apng apng;
+    image/vnd.ms-modi mdi;
+    image/vnd.pco.b16 b16;
+    image/vnd.radiance hdr rgbe xyze;
+    image/vnd.sealed.png spng spn s1n;
+    image/vnd.sealedmedia.softseal.gif sgif sgi s1g;
+    image/vnd.sealedmedia.softseal.jpg sjpg sjp s1j;
+    image/vnd.tencent.tap tap;
+    image/vnd.valve.source.texture vtf;
+    image/vnd.wap.wbmp wbmp;
+    image/vnd.xiff xif;
+    image/vnd.zbrush.pcx pcx;
+    image/wmf wmf;
+    message/global u8msg;
+    message/global-delivery-status u8dsn;
+    message/global-disposition-notification u8mdn;
+    message/global-headers u8hdr;
+    message/rfc822 eml mail art;
+    model/gltf-binary glb;
+    model/gltf+json gltf;
+    model/JT jt;
+    model/iges igs iges;
+    model/mesh msh mesh silo;
+    model/mtl mtl;
+    model/obj obj;
+    model/step+xml stpx;
+    model/step-xml+zip stpxz;
+    model/stl stl;
+    model/u3d u3d;
+    model/vnd.bary bary;
+    model/vnd.cld cld;
+    model/vnd.collada+xml dae;
+    model/vnd.dwf dwf;
+    model/vnd.gdl gdl gsm win dor lmp rsm msm ism;
+    model/vnd.gtw gtw;
+    model/vnd.moml+xml moml;
+    model/vnd.mts mts;
+    model/vnd.opengex ogex;
+    model/vnd.parasolid.transmit.binary x_b xmt_bin;
+    model/vnd.parasolid.transmit.text x_t xmt_txt;
+    model/vnd.pytha.pyox pyo pyox;
+    model/vnd.sap.vds vds;
+    model/vnd.usda usda;
+    model/vnd.usdz+zip usdz;
+    model/vnd.valve.source.compiled-map bsp;
+    model/vnd.vtu vtu;
+    model/vrml wrl vrml;
+    model/x3d+xml x3db;
+    model/x3d-vrml x3dv x3dvz;
+    multipart/vnd.bint.med-plus bmed;
+    multipart/voice-message vpm;
+    text/cache-manifest appcache manifest;
+    text/calendar ics ifb;
+    text/cql CQL;
+    text/css css;
+    text/csv csv;
+    text/csv-schema csvs;
+    text/dns soa zone;
+    text/gff3 gff3;
+    text/html html htm;
+    text/javascript js mjs;
+    text/jcr-cnd cnd;
+    text/markdown markdown md;
+    text/mizar miz;
+    text/n3 n3;
+    text/plain txt asc text pm el c h cc hh cxx hxx f90 conf log;
+    text/provenance-notation provn;
+    text/prs.fallenstein.rst rst;
+    text/prs.lines.tag tag dsc;
+    text/richtext rtx;
+    text/SGML sgml sgm;
+    text/shaclc shaclc shc;
+    text/shex shex;
+    text/spdx spdx;
+    text/tab-separated-values tsv;
+    text/troff t tr roff;
+    text/turtle ttl;
+    text/uri-list uris uri;
+    text/vcard vcf vcard;
+    text/vnd.a a;
+    text/vnd.abc abc;
+    text/vnd.ascii-art ascii;
+    text/vnd.debian.copyright copyright;
+    text/vnd.DMClientScript dms;
+    text/vnd.dvb.subtitle sub;
+    text/vnd.esmertec.theme-descriptor jtd;
+    text/vnd.exchangeable vfk;
+    text/vnd.familysearch.gedcom ged;
+    text/vnd.ficlab.flt flt;
+    text/vnd.fly fly;
+    text/vnd.fmi.flexstor flx;
+    text/vnd.graphviz gv dot;
+    text/vnd.hans hans;
+    text/vnd.hgl hgl;
+    text/vnd.in3d.3dml 3dml 3dm;
+    text/vnd.in3d.spot spot spo;
+    text/vnd.ms-mediapackage mpf;
+    text/vnd.net2phone.commcenter.command ccc;
+    text/vnd.senx.warpscript mc2;
+    text/vnd.si.uricatalogue uric;
+    text/vnd.sun.j2me.app-descriptor jad;
+    text/vnd.sosi sos;
+    text/vnd.trolltech.linguist ts;
+    text/vnd.wap.si si;
+    text/vnd.wap.sl sl;
+    text/vnd.wap.wml wml;
+    text/vnd.wap.wmlscript wmls;
+    text/vtt vtt;
+    text/wgsl wgsl;
+    text/xml xml xsd rng;
+    text/xml-external-parsed-entity ent;
+    video/3gpp 3gp 3gpp;
+    video/3gpp2 3g2 3gpp2;
+    video/iso.segment m4s;
+    video/mj2 mj2 mjp2;
+    video/mp4 mp4 mpg4 m4v;
+    video/mpeg mpeg mpg mpe m1v m2v;
+    video/ogg ogv;
+    video/quicktime mov qt;
+    video/vnd.dece.hd uvh uvvh;
+    video/vnd.dece.mobile uvm uvvm;
+    video/vnd.dece.mp4 uvu uvvu;
+    video/vnd.dece.pd uvp uvvp;
+    video/vnd.dece.sd uvs uvvs;
+    video/vnd.dece.video uvv uvvv;
+    video/vnd.dvb.file dvb;
+    video/vnd.fvt fvt;
+    video/vnd.mpegurl mxu m4u;
+    video/vnd.ms-playready.media.pyv pyv;
+    video/vnd.nokia.interleaved-multimedia nim;
+    video/vnd.radgamettools.bink bik bk2;
+    video/vnd.radgamettools.smacker smk;
+    video/vnd.sealed.mpeg1 smpg s11;
+    video/vnd.sealed.mpeg4 s14;
+    video/vnd.sealed.swf sswf ssw;
+    video/vnd.sealedmedia.softseal.mov smov smo s1q;
+    video/vnd.youtube.yt yt;
+    video/vnd.vivo viv;
+    application/mac-compactpro cpt;
+    application/metalink+xml metalink;
+    application/owl+xml owx;
+    application/rss+xml rss;
+    application/vnd.android.package-archive apk;
+    application/vnd.oma.dd+xml dd;
+    application/vnd.oma.drm.content dcf;
+    application/vnd.oma.drm.dcf o4a o4v;
+    application/vnd.oma.drm.message dm;
+    application/vnd.oma.drm.rights+wbxml drc;
+    application/vnd.oma.drm.rights+xml dr;
+    application/vnd.sun.xml.calc sxc;
+    application/vnd.sun.xml.calc.template stc;
+    application/vnd.sun.xml.draw sxd;
+    application/vnd.sun.xml.draw.template std;
+    application/vnd.sun.xml.impress sxi;
+    application/vnd.sun.xml.impress.template	sti;
+    application/vnd.sun.xml.math sxm;
+    application/vnd.sun.xml.writer sxw;
+    application/vnd.sun.xml.writer.global sxg;
+    application/vnd.sun.xml.writer.template stw;
+    application/vnd.symbian.install sis;
+    application/vnd.wap.mms-message mms;
+    application/x-annodex anx;
+    application/x-bcpio bcpio;
+    application/x-bittorrent torrent;
+    application/x-bzip2 bz2;
+    application/x-cdlink vcd;
+    application/x-chrome-extension crx;
+    application/x-cpio cpio;
+    application/x-csh csh;
+    application/x-director dcr dir dxr;
+    application/x-dvi dvi;
+    application/x-futuresplash spl;
+    application/x-gtar gtar;
+    application/x-hdf hdf;
+    application/x-java-jnlp-file jnlp;
+    application/x-java-pack200 pack;
+    application/x-killustrator kil;
+    application/x-latex latex;
+    application/x-netcdf nc cdf;
+    application/x-perl pl;
+    application/x-rpm rpm;
+    application/x-sh sh;
+    application/x-shar shar;
+    application/x-stuffit sit;
+    application/x-sv4cpio sv4cpio;
+    application/x-sv4crc sv4crc;
+    application/x-tar tar;
+    application/x-tcl tcl;
+    application/x-tex tex;
+    application/x-texinfo texinfo texi;
+    application/x-troff-man man 1 2 3 4 5 6 7 8;
+    application/x-troff-me me;
+    application/x-troff-ms ms;
+    application/x-ustar ustar;
+    application/x-wais-source src;
+    application/x-xpinstall xpi;
+    application/x-xspf+xml xspf;
+    application/x-xz xz;
+    audio/midi mid midi kar;
+    audio/x-aiff aif aiff aifc;
+    audio/x-annodex axa;
+    audio/x-flac flac;
+    audio/x-matroska mka;
+    audio/x-mod mod ult uni m15 mtm 669 med;
+    audio/x-mpegurl m3u;
+    audio/x-ms-wax wax;
+    audio/x-ms-wma wma;
+    audio/x-pn-realaudio ram rm;
+    audio/x-realaudio ra;
+    audio/x-s3m s3m;
+    audio/x-stm stm;
+    audio/x-wav wav;
+    chemical/x-xyz xyz;
+    image/webp webp;
+    image/x-cmu-raster ras;
+    image/x-portable-anymap pnm;
+    image/x-portable-bitmap pbm;
+    image/x-portable-graymap pgm;
+    image/x-portable-pixmap ppm;
+    image/x-rgb rgb;
+    image/x-targa tga;
+    image/x-xbitmap xbm;
+    image/x-xpixmap xpm;
+    image/x-xwindowdump xwd;
+    text/html-sandboxed sandboxed;
+    text/x-pod pod;
+    text/x-setext etx;
+    video/webm webm;
+    video/x-annodex axv;
+    video/x-flv flv;
+    video/x-javafx fxm;
+    video/x-matroska mkv;
+    video/x-matroska-3d mk3d;
+    video/x-ms-asf asx;
+    video/x-ms-wm wm;
+    video/x-ms-wmv wmv;
+    video/x-ms-wmx wmx;
+    video/x-ms-wvx wvx;
+    video/x-msvideo avi;
+    video/x-sgi-movie movie;
+    x-conference/x-cooltalk ice;
+    x-epoc/x-sisx-app sisx;
+}
diff --git a/nginx/nginx.conf b/nginx/nginx.conf
new file mode 100644
index 0000000..83b440c
--- /dev/null
+++ b/nginx/nginx.conf
@@ -0,0 +1,115 @@
+load_module /usr/lib/nginx/modules/ngx_http_js_module.so;
+user http;
+worker_processes auto;
+error_log /var/log/nginx/error.log error;
+
+events {
+    worker_connections 1024;
+    multi_accept on;
+}
+
+http {
+    sendfile on;
+    tcp_nopush on;
+    tcp_nodelay on;
+    server_tokens off;
+
+    access_log /var/log/nginx/access.log;
+    include mime.types;
+    default_type application/octet-stream;
+    types_hash_max_size 2048;
+    types_hash_bucket_size 128;
+
+    gzip on;
+    gzip_vary on;
+    gzip_comp_level 6;
+    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
+
+    map $http_upgrade $connection_upgrade {
+        default upgrade;
+        '' close;
+    }
+
+    geo $dollar {
+        default "$"; # DIRTY HACKS DONE CHEAP
+    }
+
+    js_import nginx.js;
+    js_shared_dict_zone zone=auth_token_cache:32k timeout=5m evict;
+
+    server {
+        listen 80 default_server;
+        listen [::]:80 default_server;
+
+        default_type text/plain;
+        root /srv/html;
+        index index.html;
+    }
+
+    # dissociate
+    server {
+        listen 80;
+        listen [::]:80;
+        server_name dissociate.mia.jetzt;
+
+        location / {
+            proxy_pass http://localhost:8001;
+            proxy_http_version 1.1;
+        }
+    }
+
+    # git
+    server {
+        listen 80;
+        listen [::]:80;
+        server_name git.mia.jetzt;
+        root /usr/share/webapps/cgit;
+        try_files $uri @cgit;
+        set $required_scope root;
+
+        location ~ /.+/(info/refs|git-upload-pack) {
+            include fastcgi.conf;
+            fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
+            fastcgi_param GIT_PROJECT_ROOT /srv/git;
+            fastcgi_pass unix:/run/fcgiwrap-git.sock;
+        }
+
+        location @cgit {
+            include fastcgi.conf;
+            fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
+            fastcgi_param CGIT_CONFIG /etc/cgit/public;
+            fastcgi_pass unix:/run/fcgiwrap-git.sock;
+        }
+
+        location /priv/ {
+            %AUTH_CHECK%
+            rewrite ^/priv/(.*) /$1 break;
+            include fastcgi.conf;
+            fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
+            fastcgi_param CGIT_CONFIG /etc/cgit/private;
+            fastcgi_pass unix:/run/fcgiwrap-git.sock;
+        }
+
+        %AUTH_LOCATIONS%
+    }
+
+    # search
+    server {
+        listen 80;
+        listen [::]:80;
+        server_name search.mia.jetzt;
+
+        set $required_scope search;
+
+        location / {
+            %AUTH_CHECK%
+            proxy_pass http://unix:/run/searxng.sock;
+        }
+
+        location /opensearch.xml {
+            proxy_pass http://unix:/run/searxng.sock;
+        }
+
+        %AUTH_LOCATIONS%
+    }
+}
diff --git a/nginx/nginx.js b/nginx/nginx.js
new file mode 100644
index 0000000..03b2dae
--- /dev/null
+++ b/nginx/nginx.js
@@ -0,0 +1,49 @@
+/** @type {import('./nginx.d.ts')} */
+
+/** @param {NginxHTTPRequest} request */
+async function validate(request) {
+    if (request.status !== 0) return;
+
+    const token = request.variables.cookie___proxy_token;
+
+    if (token == undefined) {
+        // missing token
+        request.return(401);
+        return;
+    }
+
+    const cache = ngx.shared.auth_token_cache;
+    if (cache === undefined) throw "missing shared js cache";
+
+    const requiredScope = request.variables.required_scope;
+    if (requiredScope === undefined) throw "missing required scope variable";
+
+    let scopes = cache.get(token);
+
+    if (scopes === undefined) {
+        const subrequest = await request.subrequest(`/.nginx/scopes`, {
+            args: `token=${token}`
+        });
+
+        if (subrequest.status !== 200) {
+            // invalid token
+            return request.return(401);
+        }
+
+        scopes = subrequest.responseText.split("\n");
+
+        cache.set(token, scopes.join(","));
+    } else {
+        scopes = scopes.split(",");
+    }
+
+    if (scopes.indexOf(requiredScope) === -1) {
+        return request.return(403);
+    }
+
+    return request.return(200);
+}
+
+export default {
+    validate,
+}
diff --git a/nginx/sync.py b/nginx/sync.py
new file mode 100644
index 0000000..b715d41
--- /dev/null
+++ b/nginx/sync.py
@@ -0,0 +1,59 @@
+import re
+
+from commia.prelude import *
+from commia.ssh import scp, ssh_args, ssh_prewarm
+from commia.util import with_written
+
+spacing_pattern = re.compile(r"([;,{}])$")
+
+handoff = Path("nginx/handoff.html").read_text().splitlines()
+handoff = map(lambda line: line.lstrip("\t"), handoff)
+handoff = map(lambda line: spacing_pattern.sub(r"\1 ", line), handoff)
+handoff = "".join(handoff).replace('"', '\\"').replace("$", "${dollar}")
+
+auth_check = """if ($cookie___proxy_token = "") {
+            return 303 https://$host/.nginx/handoff.html;
+        }
+        auth_request /.nginx/auth;"""
+
+auth_locations = (
+    '''location /.nginx/auth {
+                internal;
+                js_content nginx.validate;
+            }
+    
+            location /.nginx/scopes {
+                internal;
+                proxy_pass http://[::1]:8001/scopes/$arg_token;
+            }
+    
+            location /.nginx/handoff.html {
+                return 200 "'''
+    + handoff
+    + """";
+            }
+
+            location /.nginx/cookie {
+                add_header Set-Cookie "__proxy_token=${arg_token}; max-age=${arg_max_age}; path=/; samesite=strict; httponly; secure";
+                return 200;
+            }"""
+)
+
+nginx_conf = (
+    Path("nginx/nginx.conf")
+    .read_text()
+    .replace("%AUTH_CHECK%", auth_check)
+    .replace("%AUTH_LOCATIONS%", auth_locations)
+)
+
+ssh_prewarm("asylum", "secrets@bearer")
+with_written(
+    nginx_conf,
+    lambda path: scp(path, "asylum:/etc/nginx/nginx.conf"),
+)
+
+for name in ["nginx.js", "mime.types", "fastcgi.conf"]:
+    scp(f"nginx/{name}", f"asylum:/etc/nginx/{name}")
+
+if run(p([*ssh_args(), "nginx", "-t"])).returncode == 0:
+    run_check(p([*ssh_args(), "systemctl", "restart", "nginx"]))
diff --git a/nginx/types.sh b/nginx/types.sh
new file mode 100755
index 0000000..b670fdb
--- /dev/null
+++ b/nginx/types.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+set -e
+
+# generates nginx.d.ts from the latest version of njs-types published on npm
+
+test -d nginx/types && rm -r nginx/types
+mkdir nginx/types
+test -f nginx/nginx.d.ts && rm nginx/nginx.d.ts
+
+doc=$(curl https://registry.npmjs.org/njs-types)
+ver=$(echo "$doc" | jq -r '."dist-tags".latest')
+
+echo "downloading $ver"
+url=$(echo "$doc" | jq -r .versions.'"'"$ver"'"'.dist.tarball)
+curl "$url" | tar xzC nginx/types --strip-components=1
+
+echo concatenating
+for file in nginx/types/*.d.ts nginx/types/**/*.d.ts; do
+    name="${file#nginx/types/}"
+    [ "$name" = "index.d.ts" ] && continue # index.d.ts is just references. lame!
+    {
+        echo -e "// $name\n"
+        sed 's|^/// <reference .*$||' "$file" # filter out xml references
+        echo
+    } >> nginx/nginx.d.ts
+done
+rm -r nginx/types
+
+if command -v prettier >/dev/null; then
+    echo formatting
+    prettier --write nginx/nginx.d.ts
+fi
diff --git a/packages/.gitignore b/packages/.gitignore
new file mode 100644
index 0000000..05ced4a
--- /dev/null
+++ b/packages/.gitignore
@@ -0,0 +1,9 @@
+/*/pkg
+/*/src
+
+python-httpx-socks
+cgit-pink
+fw-ectool-git
+iceshrimp.net-git
+python-fasttext-predict
+python-pytomlpp
diff --git a/packages/aur.ini b/packages/aur.ini
new file mode 100644
index 0000000..811e200
--- /dev/null
+++ b/packages/aur.ini
@@ -0,0 +1,8 @@
+cgit-pink = 87afbcd732af921d9127cbbbe4aeb8f823f72d97
+fw-ectool-git = r2762.39d64fb
+iceshrimp.net-git = v2024.1.alpha+33a3601
+
+; searxng deps
+python-fasttext-predict = 043cd051e2e43ba72a9776745fde07bbb290d44a
+python-httpx-socks = bad01dbdd429fe4e14694a55f911f7810d7a39de
+python-pytomlpp = d021d021f4d38927799f38e1c91e10d70b94257b
diff --git a/packages/aur.py b/packages/aur.py
new file mode 100644
index 0000000..85658e1
--- /dev/null
+++ b/packages/aur.py
@@ -0,0 +1,121 @@
+import shlex
+import subprocess
+
+from local import build_push
+
+from commia.prelude import *
+from commia.util import check_continue, read_ini
+
+packages = read_ini("packages/aur.ini")["default"]
+ini = Path("packages/aur.ini").read_text()
+git_ignore = Path("packages/.gitignore").read_text()
+
+print("initializing new packages")
+
+for name, fix in packages.items():
+    if not Path(f"packages/{name}").exists():
+        print(f"cloning {name}")
+        run_check(
+            [
+                "git",
+                "clone",
+                f"https://aur.archlinux.org/{name}.git",
+                f"packages/{name}",
+            ]
+        )
+        if name.endswith("-git"):
+            for line in Path(f"packages/{name}/PKGBUILD").read_text().splitlines():
+                if not line.startswith("pkgver="):
+                    continue
+                ver = shlex.split(line[len("pkgver=") :])[0]
+                ini = ini.replace(f"{name} = ?", f"{name} = {ver}")
+                break
+        else:
+            if fix == "?":
+                commit = subprocess.check_output(
+                    ["git", "rev-parse", "HEAD"], cwd=f"packages/{name}", text=True
+                ).strip()
+                ini = ini.replace(f"{name} = ?", f"{name} = {commit}")
+            else:
+                run_check(["git", "checkout", fix], cwd=f"packages/{name}")
+        if not name in git_ignore:
+            git_ignore += f"{name}\n"
+            Path("packages/.gitignore").write_text(git_ignore)
+
+Path("packages/aur.ini").write_text(ini)
+
+print("checking for new versions")
+
+queue = []
+
+for name, current in packages.items():
+    if name.endswith("-git"):
+        continue
+    print(f"checking {name}")
+    path = Path(f"packages/{name}")
+    run_check(["git", "fetch"], cwd=path)
+    head = subprocess.check_output(
+        ["git", "rev-parse", "HEAD"], cwd=path, text=True
+    ).strip()
+    origin = subprocess.check_output(
+        ["git", "rev-parse", "origin/HEAD"], cwd=path, text=True
+    ).strip()
+    if current == origin:
+        print("no updates")
+        continue
+    if head != origin:
+        print()
+        run_check(["git", "diff", current, origin, ":!.SRCINFO"], cwd=path)
+        print()
+        if not check_continue():
+            continue
+    run_check(["git", "checkout", origin], cwd=path)
+    queue.append((name, current, origin))
+    print("build queued")
+
+
+for name, current in packages.items():
+    if not name.endswith("-git"):
+        continue
+    print(f"checking {name}")
+    path = Path(f"packages/{name}")
+    # update git
+    run_check(["git", "fetch"], cwd=path)
+    head = subprocess.check_output(
+        ["git", "rev-parse", "HEAD"], cwd=path, text=True
+    ).strip()
+    origin = subprocess.check_output(
+        ["git", "rev-parse", "origin/HEAD"], cwd=path, text=True
+    ).strip()
+    if head != origin:
+        print()
+        run_check(["git", "diff", head, origin, ":!.SRCINFO"], cwd=path)
+        print()
+        if not check_continue():
+            continue
+    run_check(["git", "checkout", origin], cwd=path)
+    # check for new version
+    run_check(["makepkg", "--noprepare", "--nobuild"], cwd=path)
+    ver = None
+    for line in Path(f"packages/{name}/PKGBUILD").read_text().splitlines():
+        if not line.startswith("pkgver="):
+            continue
+        ver = shlex.split(line[len("pkgver=") :])[0]
+        break
+    else:
+        raise Exception("couldn't find pkgver!")
+    if current == ver:
+        print("no update")
+        continue
+    queue.append((name, current, ver))
+
+if len(queue) == 0:
+    print("nothing to build")
+    exit()
+
+print("building new versions")
+
+for name, old, new in queue:
+    build_push(name)
+    ini = ini.replace(f"{name} = {old}", f"{name} = {new}")
+    Path("packages/aur.ini").write_text(ini)
diff --git a/packages/cgit-syntect-bat/.gitignore b/packages/cgit-syntect-bat/.gitignore
new file mode 100644
index 0000000..7c0560f
--- /dev/null
+++ b/packages/cgit-syntect-bat/.gitignore
@@ -0,0 +1 @@
+/bat/
diff --git a/packages/cgit-syntect-bat/PKGBUILD b/packages/cgit-syntect-bat/PKGBUILD
new file mode 100644
index 0000000..f4f83c2
--- /dev/null
+++ b/packages/cgit-syntect-bat/PKGBUILD
@@ -0,0 +1,28 @@
+pkgname=cgit-syntect-bat
+pkgver=0.24.0
+pkgrel=1
+pkgdesc="syntax pack based on bat for cgit-syntect"
+arch=(any)
+url="https://github.com/sharkdp/bat"
+makedepends=(bat cgit-syntect)
+source=("git+$url#commit=v$pkgver")
+sha256sums=(SKIP)
+
+pkgver() {
+	bat --version | sed -n 's/^bat \([0-9]\+\.[0-9]\+\.[0-9]\+\).*$/\1/p'
+}
+
+prepare() {
+	sed -i 's/bat .*//' bat/assets/create.sh # don't automatically build
+	sed -i 's/local submodule_prompt=unspecified/local submodule_prompt=y/' bat/assets/create.sh # don't prompt user
+	sed -i 's/^trap reverse_patches .*$//' bat/assets/create.sh # don't reverse patches
+}
+
+build() {
+	bat/assets/create.sh # prepare submodules and patches
+	MODE=compile cgit-syntect $srcdir/bat/assets/syntaxes syntax.packdump # compile syntaxes
+}
+
+package() {
+	install -Dm0755 -t "$pkgdir/usr/share/cgit-syntect" syntax.packdump
+}
diff --git a/packages/cgit-syntect/.gitignore b/packages/cgit-syntect/.gitignore
new file mode 100644
index 0000000..42b3b8e
--- /dev/null
+++ b/packages/cgit-syntect/.gitignore
@@ -0,0 +1 @@
+/cgit-syntect-*.tar*
diff --git a/packages/cgit-syntect/PKGBUILD b/packages/cgit-syntect/PKGBUILD
new file mode 100644
index 0000000..d20277c
--- /dev/null
+++ b/packages/cgit-syntect/PKGBUILD
@@ -0,0 +1,29 @@
+pkgname=cgit-syntect
+pkgver=0.2.0
+pkgrel=1
+pkgdesc="syntax highlighting for cgit based on syntect"
+arch=(x86_64 aarch64)
+url="https://git.mia.jetzt/cgit-syntect"
+license=(ISC)
+depends=(oniguruma)
+makedepends=(cargo oniguruma)
+options=(!lto)
+source=("https://git.mia.jetzt/cgit-syntect/snapshot/cgit-syntect-$pkgver.tar.gz")
+sha512sums=(SKIP)
+
+prepare() {
+	export RUSTUP_TOOLCHAIN=stable
+	cd $pkgname-$pkgver
+	cargo fetch --locked --target "$(rustc -vV | sed -n 's/host: //p')"
+}
+
+build() {
+	export RUSTUP_TOOLCHAIN=stable
+	export CARGO_TARGET_DIR=target
+	cd $pkgname-$pkgver
+	cargo build --frozen --release --all-features
+}
+
+package() {
+	install -Dm0755 -t "$pkgdir/usr/bin/" "$pkgname-$pkgver/target/release/$pkgname"
+}
diff --git a/packages/dissociate/.gitignore b/packages/dissociate/.gitignore
new file mode 100644
index 0000000..e422045
--- /dev/null
+++ b/packages/dissociate/.gitignore
@@ -0,0 +1 @@
+/dissociate-*.tar*
diff --git a/packages/dissociate/PKGBUILD b/packages/dissociate/PKGBUILD
new file mode 100644
index 0000000..f4ed01a
--- /dev/null
+++ b/packages/dissociate/PKGBUILD
@@ -0,0 +1,31 @@
+pkgname=dissociate
+pkgver=0.4.0
+pkgrel=1
+pkgdesc="simple authentication server"
+arch=(any)
+url="https://git.mia.jetzt/dissociate"
+makedepends=(cargo)
+source=("$url/snapshot/dissociate-$pkgver.tar.gz" $pkgname.service $pkgname.sysusers $pkgname.tmpfiles $pkgname.hook)
+sha256sums=(SKIP SKIP SKIP SKIP SKIP)
+
+prepare() {
+	export RUSTUP_TOOLCHAIN=stable
+	cd $pkgname-$pkgver
+	echo '[workspace]' >> Cargo.toml
+	cargo fetch --locked --target "$(rustc -vV | sed -n 's/host: //p')"
+}
+
+build() {
+	export RUSTUP_TOOLCHAIN=stable
+	export CARGO_TARGET_DIR=target
+	cd $pkgname-$pkgver
+	cargo build --frozen --release --all-features
+}
+
+package() {
+	install -Dm0755 -t "$pkgdir/usr/bin/" "$srcdir/$pkgname-$pkgver/target/release/$pkgname"
+	install -Dm0644 "$srcdir/$pkgname.service" "$pkgdir/usr/lib/systemd/system/$pkgname.service"
+	install -Dm0644 "$srcdir/$pkgname.sysusers" "$pkgdir/usr/lib/sysusers.d/$pkgname.conf"
+	install -Dm0644 "$srcdir/$pkgname.tmpfiles" "$pkgdir/usr/lib/tmpfiles.d/$pkgname.conf"
+	install -Dm0644 "$srcdir/$pkgname.hook" "$pkgdir/usr/share/libalpm/hooks/$pkgname.hook"
+}
diff --git a/packages/dissociate/dissociate.hook b/packages/dissociate/dissociate.hook
new file mode 100644
index 0000000..2d0c7a7
--- /dev/null
+++ b/packages/dissociate/dissociate.hook
@@ -0,0 +1,9 @@
+[Trigger]
+Type = Package
+Operation = Upgrade
+Target = dissociate
+
+[Action]
+Description = Restarting dissociate daemon...
+When = PostTransaction
+Exec = /bin/bash -c '/usr/bin/systemctl is-active dissociate.service -q && /usr/bin/systemctl restart dissociate.service || /usr/bin/true'
diff --git a/packages/dissociate/dissociate.service b/packages/dissociate/dissociate.service
new file mode 100644
index 0000000..180bfb3
--- /dev/null
+++ b/packages/dissociate/dissociate.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=dissociate server
+
+[Service]
+Type=simple
+User=dissociate
+Group=dissociate
+ExecStart=/usr/bin/dissociate serve /etc/dissociate/config.toml
+
+[Install]
+WantedBy=multi-user.target
diff --git a/packages/dissociate/dissociate.sysusers b/packages/dissociate/dissociate.sysusers
new file mode 100644
index 0000000..5b5e836
--- /dev/null
+++ b/packages/dissociate/dissociate.sysusers
@@ -0,0 +1 @@
+u dissociate - "dissociate server user"
diff --git a/packages/dissociate/dissociate.tmpfiles b/packages/dissociate/dissociate.tmpfiles
new file mode 100644
index 0000000..2be0fef
--- /dev/null
+++ b/packages/dissociate/dissociate.tmpfiles
@@ -0,0 +1,2 @@
+d /etc/dissociate 750 dissociate dissociate -
+d /var/lib/dissociate 750 dissociate dissociate -
diff --git a/packages/init.py b/packages/init.py
new file mode 100644
index 0000000..d556548
--- /dev/null
+++ b/packages/init.py
@@ -0,0 +1,42 @@
+import shlex
+import subprocess
+
+from commia.prelude import *
+from commia.util import read_ini
+
+packages = read_ini("packages/aur.ini")["default"]
+
+ini = Path("packages/aur.ini").read_text()
+git_ignore = Path("packages/.gitignore").read_text()
+
+for name, fix in packages.items():
+    if not Path(f"packages/{name}").exists():
+        print(f"cloning {name}")
+        run_check(
+            [
+                "git",
+                "clone",
+                f"https://aur.archlinux.org/{name}.git",
+                f"packages/{name}",
+            ]
+        )
+        if name.endswith("-git"):
+            for line in Path(f"packages/{name}/PKGBUILD").read_text().splitlines():
+                if not line.startswith("pkgver="):
+                    continue
+                ver = shlex.split(line[len("pkgver=") :])[0]
+                ini = ini.replace(f"{name} = ?", f"{name} = {ver}")
+                break
+        else:
+            if fix == "?":
+                commit = subprocess.check_output(
+                    ["git", "rev-parse", "HEAD"], cwd=f"packages/{name}", text=True
+                ).strip()
+                ini = ini.replace(f"{name} = ?", f"{name} = {commit}")
+            else:
+                run_check(["git", "checkout", fix], cwd=f"packages/{name}")
+        if not name in git_ignore:
+            git_ignore += f"{name}\n"
+            Path("packages/.gitignore").write_text(git_ignore)
+
+Path("packages/aur.ini").write_text(ini)
diff --git a/packages/local.py b/packages/local.py
new file mode 100644
index 0000000..3ef4ea9
--- /dev/null
+++ b/packages/local.py
@@ -0,0 +1,51 @@
+import os
+import shutil
+import subprocess
+import sys
+
+from commia.prelude import *
+from commia.ssh import ssh_args, ssh_opt_args
+
+
+def build_push(name):
+    path = Path(f"packages/{name}")
+    git_ignore = (path / ".gitignore").exists()
+    for pkg in path.glob("*.pkg.tar"):
+        os.remove(pkg)
+    env = {"PKGEXT": ".pkg.tar", **os.environ}
+    run_check(["makepkg", "--clean", "--syncdeps", "--cleanbuild"], cwd=path, env=env)
+    for pkg in path.glob("*.pkg.tar"):
+        run_sc(["scp", *ssh_opt_args(), pkg.as_posix(), f"asylum:/tmp/{pkg.name}"])
+        run_check(
+            [*ssh_args(), "pacman", "-U", f"/tmp/{pkg.name}"], input="y\n".encode()
+        )
+        run_sc(
+            ["sftp", "-b", "-", *ssh_opt_args(), "asylum"],
+            input=f"rm /tmp/{pkg.name}".encode(),
+        )
+        os.remove(pkg)
+    if git_ignore:
+        ignored = subprocess.check_output(
+            [
+                "git",
+                "ls-files",
+                "--others",
+                "--directory",
+                "--ignored",
+                "--exclude-from=.gitignore",
+            ],
+            cwd=path,
+            text=True,
+        )
+        for name in ignored.splitlines():
+            if ".." in name or name.startswith("/"):
+                continue
+            if (path / name).is_dir():
+                shutil.rmtree(path / name)
+            else:
+                os.remove(path / name)
+
+
+if __name__ == "__main__":
+    for name in sys.argv[1:]:
+        build_push(name)
diff --git a/packages/official.py b/packages/official.py
new file mode 100644
index 0000000..785f1cd
--- /dev/null
+++ b/packages/official.py
@@ -0,0 +1,58 @@
+from commia.prelude import *
+from commia.ssh import ssh_args
+from commia.util import check_continue, read_ini, read_inilist
+
+sections = read_inilist("packages/packages.inil", ["explicit", "ignore", "deny"])
+aur = set(read_ini("packages/aur.ini")["default"].keys())
+
+pac_explicit = set(
+    run_sc([*ssh_args(), "pacman", "-Qqe"], text=True).stdout.splitlines()
+)
+pac_all = set(run_sc([*ssh_args(), "pacman", "-Qq"], text=True).stdout.splitlines())
+
+explicit_check = sections["explicit"] - pac_explicit
+to_install = explicit_check - pac_all
+to_mark_explicit = explicit_check.intersection(pac_all)
+to_mark_dep = pac_explicit - (sections["explicit"].union(sections["ignore"]).union(aur))
+
+for package in to_install:
+    deps = set(
+        run_sc(
+            [*ssh_args(), "pacman", "-Sp", "--print-format", "%n", package]
+        ).stdout.splitlines()
+    )
+    deny = deps & sections["deny"]
+    for deny in deny:
+        print(f"package {package} depends on banned package {deny}")
+        exit(1)
+
+for package in sections["deny"]:
+    if run_silent([*ssh_args(), "pacman", "-Q", package]).returncode == 0:
+        print(f"banned package {package} already installed")
+        exit(1)
+
+if len(to_install) > 0:
+    print("to install:", " ".join(to_install))
+
+if len(to_mark_explicit) > 0:
+    print("to mark explicit:", " ".join(to_mark_explicit))
+
+if len(to_mark_dep) > 0:
+    print("to mark dependency:", " ".join(to_mark_dep))
+
+if len(to_install) + len(to_mark_explicit) + len(to_mark_dep) > 0 and check_continue():
+    if len(to_install) > 0:
+        run_check([*ssh_args(), "pacman", "-Sy", "--noconfirm", *to_install])
+
+    if len(to_mark_explicit) > 0:
+        run_check([*ssh_args(), "pacman", "-D", "--asexplicit", *to_mark_explicit])
+
+    if len(to_mark_dep) > 0:
+        run_check([*ssh_args(), "pacman", "-D", "--asdep", *to_mark_dep])
+
+cleanup = run_silent([*ssh_args(), "pacman", "-Qdtq"], text=True).stdout.splitlines()
+if len(cleanup) > 0:
+    print("to cleanup:", " ".join(cleanup))
+    if not check_continue():
+        exit()
+    run_check([*ssh_args(), "pacman", "-Rs", "--noconfirm", *cleanup])
diff --git a/packages/packages.inil b/packages/packages.inil
new file mode 100644
index 0000000..f2d5e71
--- /dev/null
+++ b/packages/packages.inil
@@ -0,0 +1,52 @@
+[explicit]
+base
+btop
+fcgiwrap
+git
+intel-ucode
+linux
+linux-firmware
+lowdown
+man-db
+man-pages
+micro
+mkinitcpio-dropbear
+mkinitcpio-netconf
+mkinitcpio-utils
+nginx
+nginx-mod-njs
+nushell
+openssh
+python
+ufw
+which
+wireguard-tools
+
+; shell
+starship
+zsh
+zsh-autosuggestions
+zsh-syntax-highlighting
+
+;neofetch
+
+libftdi ; missing dep of fw-ectool
+
+[ignore]
+cgit-syntect
+cgit-syntect-bat
+dissociate
+withdrawal
+searxng
+
+; aur
+cgit-pink
+fw-ectool-git
+iceshrimp.net-git
+; searxng deps
+python-fasttext-predict
+python-httpx-socks
+python-pytomlpp
+
+[deny]
+sudo
diff --git a/packages/searxng/.gitignore b/packages/searxng/.gitignore
new file mode 100644
index 0000000..274bcf0
--- /dev/null
+++ b/packages/searxng/.gitignore
@@ -0,0 +1 @@
+/searxng/
diff --git a/packages/searxng/PKGBUILD b/packages/searxng/PKGBUILD
new file mode 100644
index 0000000..c51e1ae
--- /dev/null
+++ b/packages/searxng/PKGBUILD
@@ -0,0 +1,50 @@
+# adapted from searxng-git 1.0.0.r3824.gac430a9ea-1
+
+pkgname=searxng
+_date=2024.05.31
+_commit=18fb701be
+pkgver=$_date+$_commit
+pkgrel=1
+pkgdesc="A privacy-respecting, hackable metasearch engine"
+arch=(any)
+url="https://github.com/searxng/searxng"
+makedepends=(python python-setuptools)
+depends=(
+	python-async-timeout
+	python-babel
+	python-brotli
+	python-certifi
+	python-dateutil
+	python-fasttext-predict
+	python-flask
+	python-flask-babel
+	python-h2
+	python-httpx
+	python-httpx-socks
+	python-jinja
+	python-lxml
+	python-markdown-it-py
+	python-pygments
+	python-pytomlpp
+	python-redis
+	python-setproctitle
+	python-uvloop
+	python-yaml
+	gunicorn
+)
+source=("git+$url#commit=$_commit" searxng.sysusers searxng.service searxng.socket)
+sha256sums=(SKIP SKIP SKIP SKIP)
+
+package() {
+	cd "$srcdir/searxng"
+	local _site_packages="$(python -c 'import site; print(site.getsitepackages()[0])')"
+
+	python setup.py install --root="$pkgdir" --optimize=1
+	python -m searx.version freeze
+
+	install -Dm644 "$srcdir/searxng.sysusers" "$pkgdir/usr/lib/sysusers.d/searxng.conf"
+	install -Dm644 "$srcdir/searxng/searx/version_frozen.py" "$pkgdir$_site_packages/searx/version_frozen.py"
+	install -Dm644 "$srcdir/searxng/LICENSE" "$pkgdir/usr/share/licenses/searxng/LICENSE"
+	install -Dm644 "$srcdir/searxng.service" "$pkgdir/usr/lib/systemd/system/searxng.service"
+	install -Dm644 "$srcdir/searxng.socket" "$pkgdir/usr/lib/systemd/system/searxng.socket"
+}
diff --git a/packages/searxng/searxng.hook b/packages/searxng/searxng.hook
new file mode 100644
index 0000000..6a99f07
--- /dev/null
+++ b/packages/searxng/searxng.hook
@@ -0,0 +1,9 @@
+[Trigger]
+Type = Package
+Operation = Upgrade
+Target = searxng
+
+[Action]
+Description = Restarting searxng daemon...
+When = PostTransaction
+Exec = /bin/bash -c '/usr/bin/systemctl is-active searxng.service -q && /usr/bin/systemctl restart searxng.service || /usr/bin/true'
diff --git a/packages/searxng/searxng.service b/packages/searxng/searxng.service
new file mode 100644
index 0000000..604df1c
--- /dev/null
+++ b/packages/searxng/searxng.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=searxng daemon
+Requires=searxng.socket
+After=network.target
+
+[Service]
+Type=notify
+User=searxng
+Group=searxng
+RuntimeDirectory=searxng
+ExecStart=/usr/bin/gunicorn searx.webapp
+ExecReload=/bin/kill -s HUP $MAINPID
+KillMode=mixed
+TimeoutStopSec=5
+PrivateTmp=true
+
+[Install]
+WantedBy=multi-user.target
diff --git a/packages/searxng/searxng.socket b/packages/searxng/searxng.socket
new file mode 100644
index 0000000..a599564
--- /dev/null
+++ b/packages/searxng/searxng.socket
@@ -0,0 +1,10 @@
+[Unit]
+Description=searxng socket
+
+[Socket]
+ListenStream=/run/searxng.sock
+SocketUser=http
+SocketMode=600
+
+[Install]
+WantedBy=sockets.target
diff --git a/packages/searxng/searxng.sysusers b/packages/searxng/searxng.sysusers
new file mode 100644
index 0000000..025903c
--- /dev/null
+++ b/packages/searxng/searxng.sysusers
@@ -0,0 +1 @@
+u searxng - "Searxng server user"
diff --git a/packages/searxng/update.sh b/packages/searxng/update.sh
new file mode 100755
index 0000000..a4d3bde
--- /dev/null
+++ b/packages/searxng/update.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+set -e
+
+pushd packages/searxng >/dev/null
+pushd searxng >/dev/null
+git fetch
+date=$(git show -s --date=format:%Y.%m.%d --format=%cd)
+commit=$(git show -s --format=%h)
+popd >/dev/null
+sed -i "s/_date=.*/_date=$date/" PKGBUILD
+sed -i "s/_commit=.*/_commit=$commit/" PKGBUILD
+popd >/dev/null
+
+echo rebuilding
+python packages/local.py searxng
diff --git a/packages/update.py b/packages/update.py
new file mode 100644
index 0000000..70e9959
--- /dev/null
+++ b/packages/update.py
@@ -0,0 +1,10 @@
+import io
+import shutil
+import sys
+from threading import Thread
+
+from commia.prelude import *
+from commia.ssh import ssh_args
+from commia.util import getch
+
+run_check([*ssh_args(), "pacman", "-Syu"])