{"id":37889521,"url":"https://github.com/korc/onefile-websrv","last_synced_at":"2026-01-16T16:55:12.567Z","repository":{"id":34710754,"uuid":"138268821","full_name":"korc/onefile-websrv","owner":"korc","description":"web server in golang","archived":false,"fork":false,"pushed_at":"2025-10-26T18:46:46.000Z","size":250,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-26T20:39:52.182Z","etag":null,"topics":["acme-client","automatic-https","cgi-server","cli-configuration","go","golang","http-server","https","reverse-proxy","server","ssl","tls","tls-proxy","unix-socket","web-server","webdav-server","websocket-server","x509certificates"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/korc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-06-22T07:15:48.000Z","updated_at":"2025-10-13T23:43:51.000Z","dependencies_parsed_at":"2024-04-23T14:02:01.889Z","dependency_job_id":"43ab7895-6d9d-458e-b822-f4ce8a5b5572","html_url":"https://github.com/korc/onefile-websrv","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/korc/onefile-websrv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/korc%2Fonefile-websrv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/korc%2Fonefile-websrv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/korc%2Fonefile-websrv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/korc%2Fonefile-websrv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/korc","download_url":"https://codeload.github.com/korc/onefile-websrv/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/korc%2Fonefile-websrv/sbom","scorecard":{"id":567617,"data":{"date":"2025-08-11","repo":{"name":"github.com/korc/onefile-websrv","commit":"404242bc1b6f6b5ee47734761d8a7c3566d5373b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.6,"checks":[{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/dockerhub.yml:1","Warn: no topLevel permission defined: .github/workflows/go.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Maintained","score":3,"reason":"4 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: third-party GitHubAction not pinned by hash: .github/workflows/dockerhub.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/korc/onefile-websrv/dockerhub.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/dockerhub.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/korc/onefile-websrv/dockerhub.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/dockerhub.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/korc/onefile-websrv/dockerhub.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/dockerhub.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/korc/onefile-websrv/dockerhub.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/dockerhub.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/korc/onefile-websrv/dockerhub.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/korc/onefile-websrv/go.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/korc/onefile-websrv/go.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/go.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/korc/onefile-websrv/go.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/go.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/korc/onefile-websrv/go.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/korc/onefile-websrv/go.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:1","Info:   0 out of   3 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   7 third-party GitHubAction dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v0.9.2 not signed: https://api.github.com/repos/korc/onefile-websrv/releases/232235619","Warn: release artifact v0.9.0 not signed: https://api.github.com/repos/korc/onefile-websrv/releases/109014379","Warn: release artifact v0.9.2 does not have provenance: https://api.github.com/repos/korc/onefile-websrv/releases/232235619","Warn: release artifact v0.9.0 does not have provenance: https://api.github.com/repos/korc/onefile-websrv/releases/109014379"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/dockerhub.yml:8"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":4,"reason":"SAST tool is not run on all commits -- score normalized to 4","details":["Warn: 2 commits out of 5 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T15:24:16.522Z","repository_id":34710754,"created_at":"2025-08-20T15:24:16.522Z","updated_at":"2025-08-20T15:24:16.522Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28480081,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acme-client","automatic-https","cgi-server","cli-configuration","go","golang","http-server","https","reverse-proxy","server","ssl","tls","tls-proxy","unix-socket","web-server","webdav-server","websocket-server","x509certificates"],"created_at":"2026-01-16T16:55:11.845Z","updated_at":"2026-01-16T16:55:12.551Z","avatar_url":"https://github.com/korc.png","language":"Go","readme":"# README\n\n## Installing\n\n### Quick-start examples\n\n#### Serving current directory on port 8080 (Docker version)\n\n```sh\ndocker run --rm -it -v \"$PWD:/var/www/html:ro\" -p 8080:80 korc/onefile-websrv\n```\n\n#### Serving current directory on port 8080 (Go version)\n\n_Install [Go](https://golang.org/dl/)_\n\n```sh\ngo install github.com/korc/onefile-websrv@latest\n~/go/bin/onefile-websrv -listen :8080\n```\n\n#### Public HTTPS server with valid, auto-generated Let's Encrypt certificates\n\n(replace `example.com` with your real public hostname)\n\n```sh\ngo install github.com/korc/onefile-websrv@latest\nmkdir acme-certs\nsudo ~/go/bin/onefile-websrv -listen :443 -acmehost example.com -cert $PWD/acme-certs -map /=file:/var/www\n```\n\nCheck out systemd approach below for more secure setup.\n\n#### With Docker\n\nServing content from `/data/web/html`:\n\n```sh\ndocker build -t websrv https://github.com/korc/onefile-websrv.git\ndocker run --name websrv -u 33:33 -p 80:8080 -v /data/web:/var/www websrv -listen :8080\n```\n\n#### Using with systemd\n\n```sh\ngo install github.com/korc/onefile-websrv@latest\ninstall go/bin/onefile-websrv /usr/local/bin/websrv\ncurl https://raw.githubusercontent.com/korc/onefile-websrv/master/websrv.service | sudo tee /etc/systemd/system/websrv.service\nsudo vi /etc/systemd/system/websrv.service # modify command line options for your needs\nsystemctl daemon-reload \u0026\u0026 systemctl enable websrv \u0026\u0026 systemctl start websrv\nsystemctl status websrv\n```\n\n### Listening on low-number ports, chroot and non-root user issues\n\nwebsrv can change user id after start (required for low-level port listen and chroot), but unfortunately that's currently broken in Golang's Linux implementation (some process threads might remain running as `root`). If you don't want to run as `root` (not recommended anyway), and want to use those high-privileged functions, then it's best to set appropriate `capabilities(7)` with `setcap(8)` program (ex: `setcap cap_net_bind_service,cap_sys_chroot=ep websrv`), and then run as target user (ex: `www-data`).\n\n## Configuration\n\n### Command-line options\n\n```text\nwebsrv -h\n  -acl value\n      [{\u003cmethods..\u003e}]\u003cpath_regexp\u003e=\u003crole\u003e[+\u003crole2..\u003e]:\u003crole..\u003e (multi-arg)\n  -acmehost string\n      Host names (comma-separated) allowed for automatically issued ([ACME](https://en.wikipedia.org/wiki/Automatic_Certificate_Management_Environment)) certificates, -cert will be cache dir\n  -acmehttp string\n      Listen address for ACME http-01 challenge (default \":80\")\n  -args-env string\n        read arguments from environment \u003cprefix\u003e1..\u003cprefix\u003eN (default \"WEBSRV_ARG\")\n  -args-file string\n        read args from file, one per line\n  -auth value\n      [\u003crole\u003e[+\u003crole2\u003e]=]\u003cmethod\u003e:\u003cauth\u003e (multi-arg)\n  -cert string\n      SSL certificate file or autocert cache dir\n  -cert-fallback\n      Certificate file to use if ACME fails\n  -chroot string\n      chroot() to directory after start\n  -key string\n      SSL key file\n  -listen string\n      Listen ip:port or /path/to/unix-socket (default \":80\")\n  -loglevel string\n      Max log level (one of FATAL, ERROR, WARNING, INFO, VERBOSE, DEBUG) (default \"info\")\n  -map value\n      [\u003cvhost\u003e]/\u003cpath\u003e=\u003chandler\u003e:[\u003cparams\u003e] (multi-arg, default '/=file:')\n  -user string\n      Switch to user (NOT RECOMMENDED)\n  -cors value\n      [{host_re=\u003cvhost_re\u003e,methods=\u003cmethod:..\u003e,headers=\u003chdr:..\u003e,creds=\u003cstr\u003e}]\u003cpath_re\u003e=\u003callowed_origin_re\u003e (multi-arg)\n  -wstmout int\n      Websocket alive check timer in seconds (default 60)\n  -reqlog string\n      URL to log request details to (supports also unix:///dir/unix-socket:/path URLs)\n```\n\nOptions marked with `multi-arg` can be specified multiple times on command-line, and will add to previous configuration. Other options are meant to be set only once.\n\n#### Command-line through environment\n\n- by default, arguments can be also specified through environment variables `WEBSRV_ARG1` .. `WEBSRV_ARG\u003cn\u003e`\n  - the prefix of environment variable can be set via `-args-env` option\n\n#### Command-line from file\n\n- `-args-file` can be used to set a file to read arguments from, one per line\n- `-args-env` is processed before, so `WEBSRV_ARG1=-args-file WEBSRV_ARG2=/some/path/file` can be used to set that file via environment as well\n- `-args-file` is a multi-arg, and can be subsequently added via files themselves\n\n### URL path mapping\n\n- `-map` option in `hostname/path=handler:params` format can be used to map different paths to different handlers\n  - optional `hostname` can be used for virtual hosting, empty value for all hosts\n  - starting with `@` will be saved for later use (like `.ext` option for file: handlers)\n- additional `-map` entries add more mappings\n- supported `handler` types:\n  - `file:` statically serve files from directory specified in `params`, or current working directory if empty\n    - `{..}` options can include `404=/some/other/path` or `404=@saved_handler/`  or `.ext=@saved_handler/`\n  - `webdav:` WebDAV handler for directory `params`, or memory-only storage if empty. Options between `{..}` before path:\n    - `ctype=\u003cCONTENT_TYPE\u003e` use `CONTENT_TYPE` for file content type (was: `-wdctype`)\n    - `unsafe=1` use `webdav.Dir` instead of symlink-checking (more safe) custom FS provider\n  - `websocket:` (alias `ws`) connects a websocket to TCP or UNIX socket\n  - `http:` pass request to HTTP backend\n  - `debug:` client request debug\n    - comma-separated options available after `:`\n      - `json` output data in JSON format\n      - `no-hdr` do not include request headers in JSON output\n      - `no-auth` do not include obtained roles info in json\n      - `path=x.y.z` show only defined path from JSON output (ex: `path=TLS.peers[0].cn`)\n      - `tls-cs` include full tls.ConnectionState in JSON output\n  - `cgi:` Run a CGI script specified by `params`.\n  - `jwt:` generate JWT token\n  - `ws-proxy:` WebSocket proxy service, to be used with `ws_proxy`\n\n#### WebSocket handler\n\n- `params` contains target where websocket is connected to\n  - `HOST:PORT` or `tcp:HOST:PORT` to connection via TCP to _HOST:PORT_\n  - `tls:HOST:PORT` to connect using TLS over TCP\n  - `unix:/PATH/SOCKET` for UNIX socket\n  - `exec:COMMAND` to run COMMAND using `sh -c`\n    - prefix `{sh=SHELL}` for alternate shell\n    - prefix `{no-c=1}` for no `-c` option after shell command\n    - prefix `{sep=SEPARATOR}` to split string after `exec:` into arguments with _SEPARATOR_\n  - `mux:ID` to share a websocket with other clients connected to the same `ID`\n- supported options before path in `{...}`\n  - `type=text` to change default message type to text\n  - `re=REGEXP` to match grouped params like `$1` in address from request URL path with regexp\n\n#### HTTP handler\n\n- `params` must be complete URL starting with `http:`, `https:`, `unix:` or `wsprx:`\n  - `wsprx` is handled by `ws-proxy:` mapped server, hostname component as name of it (example below)\n- supports unix sockets in the format of `unix:///path/to/unix-socket:/urlpath`\n- comma-separated options between `{...}` before URL:\n  - `cert` and `key` options to set TLS backend client certificate and key files\n  - forward client certificate data to backend in specified HTTP header:\n    - `fp-hdr` SHA256 fingerprint\n    - `cn-hdr` subject CN attribute\n    - `subj-hdr` subject in text form\n    -  `cert-hdr` hex-encoded client certificate\n  - `del-hdr=x-header-name:x-header2-name` to remove request header from client\n  - `set-hdr:x-header-name=VALUE` to set a request header\n  - `no-xff=1` to remove `X-Forwarded-For` header containing client IP and do not send `X-Forwarded-Proto`\n  - `no-gzip=1` do not send `Accept-Encoding: gzip`\n  - `verify=0` to allow making insecure HTTPS requests\n  - `fix-ws-hdr=1` make sure `Sec-Websocket-*` headers are sent as `Sec-WebSocket-*`\n  - `ca=\u003cfilename\u003e` to set remote RootCAs PEM file\n\n#### Example: Using HTTP handler with `wsprx` schema\n\nGoal: passing backend http server to external front-end. External server possibly publicly accessible, backend possibly in the internal network (a'la ngrok).\n\n- front-end web service:\n  `onefile-websrv -map /=http:wsprx://backend -map /.srv=ws-proxy:{listener=1}backend`\n- back-end web service:\n  `onefile-websrv -map /=file:/data/web/html -listen 127.0.0.1:8000`\n- back-end to front-end connector (from `cmd/ws_proxy`):\n  `ws_proxy -ws ws://front-end-srv/.srv -connect 127.0.0.1:8000`\n\nNOTE: If front-end is accessible from public internet, you should additionally protect `/.srv` endpoint properly with `-acl` options.\n\n#### WebSocket Proxy handler\n\n- `params` is a internal name for this proxy. options:\n  - `{listener=1}` make this a server socket for `ws_proxy` endpoint\n  - `{re=...}` searches URL.Path, and `params` as template for name\n    - ex: `-map /prx/=ws-proxy:{re=^/prx/(.+)}prx-$1`\n\n#### Debug handler\n\nIncludes client certificate hash, which can be used for `-auth` option's `Cert` method\n\n#### CGI handler\n\nBefore program name, can specify environment and args with `{` `}`\n\n##### Examples\n\n- `{AAAA,BBBB=123,arg:--dir,arg:/var/www}/usr/lib/cgi/program`\n  - `AAAA` will be copied from host env, `BBBB` will be set to `123`, program will be executed with 2 arguments: `--dir` and `/var/www`\n\n#### JWT handler\n\n- secret source specified by `params`\n- source can be prefixed with `file:` to read source from file, or `env:` to read from environment variable\n- following comma-separated options can prefixed with `{...}` before source\n  - `b64=1` decode secret from base64\n  - `alg={ES256|ES384|ES512|RS256|RS384|RS512|PS256|PS384|PS512|HS256|HS384|HS512}` generation algorithm\n    - default algorithm is `HS256`\n    - `RS*` and `PS*` source must be PEM-encoded RSA private key (PKCS#1)\n    - `ES*` source is EC-DSA key\n  - `\u003ckey\u003e=\u003cvalue\u003e`: set `key` in the issued claim to `value`\n    - if `key` ends with `_claim`, that is removed\n    - if `key` ands with `\u003cclaim\u003e_repl`, it must contain sed-like string replacement in `@regex@replacement@` format, which will be applied to the claim `\u003cclaim\u003e`\n      - any character be used instead of `@`\n      - ex: `{aud=req:path,aud_repl=@.*/@@}` assigns `aud` to a filename in the path\n    - `value` can be value string, or a value solved from request (cf. `Parameters from request` section below)\n      - also, `ts:\u003cformat\u003e` for unix timestamp based on following:\n        - basic format is `+duration` or `-duration` to add or subtract from current time\n        - can prefix duration with\n          - `today` to make relation based on start of the day in server localtime\n          - `q:` get duration relative to issue time from URL query\n    - `exp` is by default set to `ts:+5m`, use `exp=` with empty value to explicitly disable JWT expiration\n\n##### Examples:\n\n- `-map /acl/get=jwt:{b64=1,exp=ts:+1h,aud=q:target,nbf=ts:q:nbf}bXktc2VjcmV0`\n  - HS256 signed with shared secret `my-secret`, 1 hour expiration, audience from `target` query parameter, valid-from time from `nbf` query parameter (default=time of request)\n- `-map /login=jwt:{exp=ts:today+25h,sub=crt:cn,alg=ES256}file:jwt.key`\n  - signed with EC-DSA key in `jwt.key`, `sub` in claims from client's x509 certificate subject `CN` attribute, expiring on next day at 1am\n\n### Parameters from request\n\nSeveral options support retrieving a value from request. The syntax is as following:\n\n- `str:` plain string following `str:`\n- `crt:` client certificate data\n  - `cn` subject common name\n  - `subj` full subject\n  - `fp` certificate sha256 fingerprint\n  - `crt` base64-encoded certificate\n- `q:\u003cname\u003e` value of URL query parameter `\u003cname\u003e`\n- `post:\u003cname\u003e` POST form value\n- `hdr:\u003cname\u003e` HTTP request header\n- `env:\u003cname\u003e` server environment variable\n- `auth:\u003cvalue\u003e`\n  - `bearer` Authorization Bearer value\n  - `basic-usr`, `basic-pwd`  respective Basic auth user/password values\n- `req:` a value from request parameter\n  - `raddr` client remote address (with port number)\n  - `rip` client remote IP\n  - `host` requested Host\n  - `path` URL path\n- `jwt:\u003cclaim\u003e:\u003csrc\u003e`\n  - parse JWT from `\u003csrc\u003e` (same syntax as above), and retrieve value of claim named `\u003cclaim\u003e`. The name is assumed to be must be URL-escaped.\n- `unescape:\u003csrc\u003e`\n  - solve `\u003csrc\u003e` via request, and url-unescape it\n  - if `\u003csrc\u003e` does not contain `:`, it is assumed to be verbatim string\n- `tmpl:\u003csrc\u003e`\n  - construct string from template, which is parameter defined in `\u003csrc\u003e`\n  - `.req` data is set to current request\n  - additional functions defined\n    - `rp \u003cparam\u003e \u003creq\u003e` function is added to retrieve other parameters from request\n    - `b64 \u003cbytes\u003e`, `b64url \u003cbytes\u003e`, `b64dec \u003cstr\u003e`, `b64decurl \u003cstr\u003e` encode/decode with normal/url encoding. decode returns values in []byte type, encode in string\n    - `stob` convert string to bytes\n    - `atoi` convert string to integer\n    - `map \u003ckey\u003e \u003cvalue\u003e ...` create a map of values\n    - `json` convert map to json []byte value\n  - ex: `tmpl:env:ENV_TEMPLATE_VAR`, with `ENV_TEMPLATE_VAR` containing `eyJhbGciOiJIUzI1NiJ9.{{b64url (json (map \"sub\" (rp \"q:sub\" .req)))}}.{{rp \"q:sig\" .req}}`\n\n### Access control\n\n- `-acl` option will define mapping between URL paths and required roles\n  - `path_regexp` is defined by regular expression, like `^/admin/`\n    - add `?` before regex (ex: `?^/xyz/.*session_id=.*`) to check full RequestURI including query part (not only Path) for match\n  - in curly braces before path regexp can set comma-separated params\n    - `host:\u003chostname\u003e` to apply only for particular virtual hosts (req with `Host: hostname`)\n    - `GET`, `POST`, etc. to filter by HTTP methods\n    - `onfail:\u003cURL\u003e` redirect to URL when auth fails. can use `@param@` placeholders to solve into url-escaped values from request (ex: `@req:host@`)\n      - use `file:` URL to serve file instead of redirection\n  - `:` separates alternate roles (OR operation)\n  - `+` makes all specified roles to be required (AND operation)\n    - can be used to implement multi-factor auth\n- `-auth` option can be used to add new roles\n  - multiple roles can be assigned with one method\n  - `auth` value is method-specific\n  - can use environment variables in form of `${variable_name}` in `auth` part (presence in environment is mandatory)\n  - possible values for `method` parameter\n    - `Basic`\n      - HTTP Basic authentication (WEAK security)\n      - `auth` is a Base64-encoded value of `username:password`\n    - `Cert`\n      - SSL Client X.509 certificate authentication\n      - `auth` as hex-encoded value of SHA-256 hash of certificate's binary (DER) data\n      - if `auth` starts with `file:`, certificate is read from file on disk and it's hash is used instead\n    - `CertBy`\n      - `auth` can be hex-encoded value of client CA certificate's binary\n      - `file:` in the beginning of `auth` will load CA certificate from file\n    - `CertKeyHash`\n       `auth` is hex-encoded SHA256 hash of client certificate's public key (SHA256 of ASN1 from `ssh-keygen -e -m pkcs8` and `certtool --pubkey-info`)\n       `file:` prefix make keys to be loaded from specified file instead\n         - can read OpenSSH `authorized_keys` with `ssh-rsa` keys, and PEM files with `PUBLIC KEY` or `CERTIFICATE` data\n    - `JWT`\n      - `auth` value is RSA or ECDSA private or public key in PEM format, unless `{hs=1}` option is given\n        - use `env:\u003cvarname\u003e` or `file:\u003cfilename\u003e` to read value from environment or file\n      - `{..}` options values\n        - `src=\u003creq_param\u003e` define jwt source, cf. `Parameters from request` for `\u003creq_param\u003e` format\n          - can use `src_xxx` to arbitrarily define multiple sources\n        - `no-bearer=1` do not check `Authorization: Bearer ...` header by default\n        - `hs=1` use `auth` value as secret key for HMAC signature\n        - `b64=1` decode `auth` value with base64\n        - `aud=\u003ctype\u003e:\u003cvalue\u003e` or `aud=path` - determine what is going to be checked for `aud` \"*Audience*\" claim\n          - `type` and `value` use same syntax as claim string values in [JWT handler](#jwt-handler) (no `ts:` timestamp).\n        - `aud-re=\u003cregexp\u003e` aud value (`path` by default, can be overwritten by `aud=`) will be matched against regexp, if subgroups found then first group will be used as value\n        - `test=claim:\u003cname\u003e:\u003ctest\u003e` or `test_\u003cxxx\u003e=claim:\u003cname\u003e:\u003ctest\u003e`\n          - `\u003cname\u003e` is a url-escaped name of a claim to test\n          - `\u003ctest\u003e` is a plain string, or a request parameter if contains `:`\n    - `JWTSecret` *DEPRECATED* in favor of `JWT`\n      - checks if JWT from `Authentication: Bearer` header is signed by specific authority\n      - `auth` contains authority's shared secret\n      - can prefix `auth` with `{cookie|header|query=XXX}` to additionally look JWT token from specified cookie, header or query parameter named `XXX`. multiple locations have to be separated with comma.\n        - ex: `-auth viewer=JWTSecret:{cookie=viewacces,query=va}MySecretJWTKey`\n    - `IPRange`\n      - checks client's remote IP\n      - `auth` is IP address with network mask length in format of `ip/masklen`\n      - can start with `file:` to read ip ranges from file, lines starting with `#` are ignored\n      - `{xff=..}` colon-separated list of reverse proxy IP's which can set `X-Forwarded-For` header for client IP\n    - `JWTFilePat` *DEPRECATED*\n      - `auth` specifies file (pattern) containing accepted JWT tokens signed with:\n        - secrets, in format of `hash:url-base64-encoded-secret`\n        - RSA public keys, in format of `rsa:base64-encoded-n-value`\n          - `e` is assumed to be `0x10001`\n      - if letters \"`**`\" are found inside filename, they are replaced with pattern constructed from:\n        - URL path, URL path with extensions of last element removed (one-by-one), and each path component removed one-by-one from the end\n        - Ex: `-acl ^/adm/=xxx -auth xxx=JWTFilePat:/data/webauth/**.jwt` and access to `/adm/test.123.html` will result in checking of files\n            - `/data/webauth/adm/test.123.html.jwt`\n            - `/data/webauth/adm/test.123.jwt`\n            - `/data/webauth/adm/test.jwt`\n            - `/data/webauth/adm.jwt`\n        - because of cost associated with checking for `.jwt` files, auth is applied only when path requires authentication\n    - `File`\n      - file existence check\n      - options available with `{..}` prefix:\n        - `nofile` inverse condition, and succeed if file does NOT exist\n        - `re-path` treat auth value as regular expression, and `re-path` as pathname with `$\u003cnr\u003e` subgroup expansion pattern\n          - ex: `-map /=webdav:/data/ -auth nofile=File:{no-file=1,re-path=/data/$1}/(.+) -auth ip4all=IPRange:0.0.0.0/0 -acl {PUT}^/=nofile -acl {GET}^/=ip4all -acl ^/=nobody`\n            - create a WebDAV mapping for `/data/`, where you can upload only new files\n    - `HTTP`\n      - make a HTTP sub-request to URL at parameter\n        - if value starts with `tmpl:`, it will be processed as template in _Parameters from request_, documented above\n      - options set with `{..}`:\n        - `method` use something else than `GET`\n        - `need-hdr` colon-separated list of headers required to even start testing (ex. `Authorization`)\n        - `cp-hdr` colon-separated list of headers to copy from original request\n        - `set-hdr:xxx` set header `xxx` to a specified value when making request\n          - value can start with `tmpl:`, see above\n        - `success` response code which to be considered success\n    - `GeoIP`\n      - look up record from MaxMind's GeoIP database and check record value\n      - options via `{..}`\n        - `file=\u003cfilename.mmdb\u003e` set database, MANDATORY\n        - `rprx=\u003cip1\u003e:\u003cip2..\u003e` list of reverse proxy servers for `X-Forwarded-For`, from closest to farthest\n        - `key=\u003ca\u003e:\u003cb..\u003e` set record value key, defaults to `country:iso_code`\n      - example usage: `-auth \"jpn=GeoIP:{file=/usr/share/GeoIP/GeoLite2-Country.mmdb,rprx=127.0.0.1}JP\"`\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkorc%2Fonefile-websrv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkorc%2Fonefile-websrv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkorc%2Fonefile-websrv/lists"}