{"id":27247405,"url":"https://github.com/pancakesarchitect/levior","last_synced_at":"2025-04-10T22:53:59.059Z","repository":{"id":178117665,"uuid":"504980267","full_name":"PancakesArchitect/levior","owner":"PancakesArchitect","description":"Web to Gemini proxy. Browse the www from the comfort of your favorite Gemini browser !","archived":false,"fork":false,"pushed_at":"2024-07-25T11:51:52.000Z","size":586,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-10T22:53:53.426Z","etag":null,"topics":["gateway","gemini","gemini-protocol","gemini-proxy","gemini-server","http-client","http-proxy","linked-data","proxy","socks5","zim"],"latest_commit_sha":null,"homepage":"https://levior.gitlab.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PancakesArchitect.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-19T00:40:53.000Z","updated_at":"2025-03-23T07:35:14.000Z","dependencies_parsed_at":"2023-12-05T15:58:35.969Z","dependency_job_id":"0da95213-a92d-4316-bdf5-7d244896be24","html_url":"https://github.com/PancakesArchitect/levior","commit_stats":null,"previous_names":["pinnaculum/levior","pancakesarchitect/levior"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PancakesArchitect%2Flevior","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PancakesArchitect%2Flevior/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PancakesArchitect%2Flevior/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PancakesArchitect%2Flevior/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PancakesArchitect","download_url":"https://codeload.github.com/PancakesArchitect/levior/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248312172,"owners_count":21082638,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["gateway","gemini","gemini-protocol","gemini-proxy","gemini-server","http-client","http-proxy","linked-data","proxy","socks5","zim"],"created_at":"2025-04-10T22:53:58.459Z","updated_at":"2025-04-10T22:53:59.048Z","avatar_url":"https://github.com/PancakesArchitect.png","language":"Python","funding_links":["https://ko-fi.com/cipres","https://liberapay.com/galacteek"],"categories":[],"sub_categories":[],"readme":"# Web to Gemini proxy\n\n![logo](https://gitlab.com/cipres/levior/-/raw/master/media/img/levior-256.png)\n\n\u003e *Pāpiliō levior est ave* (The butterfly is lighter than the bird)\n\n*levior* (a latin word meaning *lighter*) is a web (HTTP/HTTPs) to\n[Gemini](https://geminiprotocol.net) proxy.\nIt converts web pages (as well as Atom/RSS feeds) on-the-fly to\nthe [gemtext](https://geminiprotocol.net/docs/gemtext.gmi) format,\nallowing you to browse the web with any Gemini browser.\n\n- Builds an (RDF) graph from the visited pages using linked data.\n\n- Supports Javascript rendering and can therefore be used to browse\ndynamic websites.\n\n- Supports serving other types of content, like ZIM files (the\narchive format used by Wikipedia), making it possible to browse complete wikis\nthrough Gemini ([see the config file](https://gitlab.com/cipres/levior/-/raw/master/examples/levior.zim.yaml)).\n\n[![pipeline status](https://gitlab.com/cipres/levior/badges/master/pipeline.svg)](https://gitlab.com/cipres/levior/-/commits/master)\n[![coverage report](https://gitlab.com/cipres/levior/badges/master/coverage.svg)](https://gitlab.com/cipres/levior/-/commits/master)\n\n## Supporting this project\n\nIf you want to support this project, you can\nmake a donation [here](https://ko-fi.com/cipres) (or\n[here](https://liberapay.com/galacteek)).\n\nYou can get in touch via [misfin](https://gitlab.com/cipres/misfin)\nat the following misfin address: *cipres AT hashnix.club*.\n\n## Installation\n\n### AppImage\n\nYou can get the latest AppImage (for the *x86_64* platform) [here](https://gitlab.com/cipres/levior/-/releases/continuous-master/downloads/levior-latest-x86_64.AppImage). This would install levior in *~/.local/bin*:\n\n```sh\ncurl -L -o ~/.local/bin/levior https://gitlab.com/cipres/levior/-/releases/continuous-master/downloads/levior-latest-x86_64.AppImage\nchmod +x ~/.local/bin/levior\n```\n\n### Manual install\n\nClone the repo and create a virtualenv:\n\n```sh\ngit clone https://gitlab.com/cipres/levior \u0026\u0026 cd levior\npython3 -m venv venv; source venv/bin/activate\n```\n\nUpgrade pip and install:\n\n```sh\npip install -U pip\npip install .\n```\n\nFor zim or uvloop support, install the extra requirements:\n\n```sh\npip install '.[zim]'\npip install '.[uvloop]'\n```\n\nFor Javascript rendering, install the *js* extra:\n\n```sh\npip install '.[js]'\n```\n\n### Manual install (arm, aarch64, Raspberry Pi, and others)\n\nOne of the dependencies, *aiogemini*, requires the\n[cryptography](https://pypi.org/project/cryptography/) package, which since\nversion *35.0* requires Rust to build, which might not be available on your system.\nIf you don't have rust, you can install an older version of the cryptography\npackage that does not require rust, by running:\n\n```sh\npip install -U pip\n\nCRYPTOGRAPHY_DONT_BUILD_RUST=1 pip install 'cryptography==3.4.8'\n\npip install .\n```\n\n## Usage\n\n*levior* can be configured from the command-line or via a *YAML* config file\nIf a config file is provided, settings from both sources are merged to create\na unique config, with the config file settings taking precedence.\nSee [the example config file](https://gitlab.com/cipres/levior/-/raw/master/examples/levior.yaml). URL rules can only be configured with a config file.\n\nlevior uses the [OmegaConf library](https://omegaconf.readthedocs.io) to\nparse the YAML config files, therefore all the specific syntax elements\nsupported by *OmegaConf* can be used in your configuration files. levior\nprovides several [resolvers](https://omegaconf.readthedocs.io/en/2.3_branch/custom_resolvers.html) that you can use inside your config file.\n\n\n```sh\nlevior\nlevior -d --mode=proxy\nlevior -c config.yaml\n```\n\nOnce *levior* is running, open your gemini browser and go to\n[gemini://localhost](gemini://localhost).\n\nProxies (HTTP, Socks4 and Socks5) are supported.\n\n### Generating a new configuration file\n\n```sh\nlevior --config-gen levior.yaml\nlevior -c levior.yaml\n```\n\n## Daemonization\n\nUse **--daemon** or **-d** to run levior as a daemon, or set the\n*daemonize* setting in the config file:\n\n```yaml hl_lines=\"1\"\ndaemonize: true\npid_file_path: levior.pid\n```\n\n## Custom SSL certificate\n\nBy default, *levior* will use a built-in SSL certificate and key that is\nappropriate when the service is listening on *localhost*.\n\nIf you are configuring *levior* to listen on a non-local interface, you will\nfirst need to generate your own SSL keypair. Then, in your config file, set the\n*cert* and *key* attributes to point to the file paths of your SSL certificate\nand key.\n\n```yaml hl_lines=\"2 3\"\nhostname: 'mydomain.com'\ncert: 'mydomain.crt'\nkey: 'mydomain.key'\n```\n\nYou can also use the **--cert** and **-key** command-line parameters.\n\n## Logging\n\n### Access log\n\nRequests are logged as gemtext links. Use **--log-file** if you want the\naccess log to be written to a file.\n\n- If you are not running *levior* as a daemon, and you don't specify an access\n  log file path, requests are logged to the console\n- If you are running *levior* as a daemon, requests are logged to the specified\n  log file (or the default: *levior-log.gmi*)\n\n### Access log server endpoint\n\nSet *access_log_endpoint* to *true* in your config file to enable the access\nlog endpoint **/access_log** on the server. This endpoint shows the\nproxy's access log in the gemtext format.\n\n```yaml hl_lines=\"1\"\naccess_log_endpoint: true\n```\n\n## Restricting access by IP address or network\n\nYou can restrict access to the proxy by declaring a list of\nallowed IP addresses or networks in your config file.\n\n```yaml\nclient_ip_allow:\n  - 127.0.0.1\n  - 10.0.1.0/24\n```\n\n## RDF\n\n*levior* uses an RDF graph to store various attributes about the pages\nthat are accessed via the proxy:\n\n- The page's title\n- Every link contained in the page is defined as being [referenced](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/references) by the source page\n- Gemtext headers in the page are the [table of contents](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/tableOfContents)\n\nIf you want to disable the automatic graphing of pages, disable\n*graph_visited_pages* in the config:\n\n```yaml\ngraph_visited_pages: false\n```\n\n## URL mapping\n\nDefine *urlmap* in your config file to map specific paths (on levior's\ngemini server) to certain URLs.\n\n```yaml\nurlmap:\n  # When /searx is requested without a gemini query, it will send\n  # an input response. When the input is sent back, it will redirect the\n  # user to \"https://searx.be/search?q={input}\"\n\n  /searx:\n    input_for: https://searx.be/search?q=\n    route_name: Search with SearX\n\n  /liteduck:\n    input_for: https://lite.duckduckgo.com/lite/?q=\n    route_name: DuckDuckGo Lite search\n\n  # Mapping with variables in the path\n  # /z/test =\u003e https://searx.be/search?q=test\n  /z/{query}:\n    url: https://searx.be/search?q={query}\n```\n\nIf you set *route_name*, the route will appear on levior's homepage.\n\n## URL rules\n\nYou can define your own rules in order to apply some processing on the gemtext\nthat will be sent to the browser, or return a specific gemini response.\n\nA rule must define which URL(s) to match with the *url* attribute, which can\nbe a regular expression or a list of regular expressions. If the *response*\nattribute is defined, the *status* attribute must be set as an\n[aiogemini Status code](https://github.com/keis/aiogemini/blob/master/aiogemini/__init__.py). Here are some basic examples of custom rules:\n\n```yaml hl_lines=\"3 4\"\nrules:\n  - url: '^https?://[\\\\w.-]*google'\n    response:\n      status: 'PROXY_REQUEST_REFUSED'\n```\n\n```yaml\nrules:\n  - url: '^https?://www.example.org'\n    response:\n      status: 'SUCCESS'\n      text: |-\n        Gemtext content\n```\n\nSet *js_render* in the rule to enable JS rendering.\n\n```yaml hl_lines=\"3\"\nrules:\n  - url: '^https?://www.requires-js.org'\n    js_render: true\n```\n\n### Caching\n\nThe raw content of the web resources fetched by the proxy can be cached.\nThe result of the *geminification* of the pages (the gemtext document)\nis never cached.\n\nSet the *cache* attribute in your rule to cache the data. The *ttl*\n(time-to-live) attribute determines the expiration lifetime (in seconds) for the\nresource's content in the cache. The data will be served from the cache\nuntil the ttl expires (subsequent requests will trigger a refetch).\n\n```yaml hl_lines=\"3 4\"\nrules:\n  - url: '^https?://www.thingstokeep.org'\n    cache: true\n    ttl: 86400\n```\n\n#### Caching the access log\n\nThe access log can be persisted in the cache via the *persist_access_log*\nsetting (or with **--persist-access-log**). This is disabled by default.\n\n```yaml\npersist_access_log: true\n```\n\n#### Caching links on pages\n\nSpecific links to cache the page for a few days (or forever) can be shown\nat the top of the page, with the *page_cachelinks* setting. This makes\nit easy to cache a page that you've just browsed without having to define\ncustom rules.\n\n```yaml\npage_cachelinks: true\n```\n\n### Includes\n\nIt is also possible to load predefined rules by using the *include* keyword\nin your config file. If you prefix the path with *levior:*, it will be loaded\nfrom the builtin [rules library](https://gitlab.com/cipres/levior/-/tree/master/levior/configs) (please [open a PR](https://gitlab.com/cipres/levior/-/merge_requests/new) to submit new rules), otherwise it is assumed to be a local file.\n\n```yaml\ninclude:\n  - levior:sites/francetvinfo.yaml\n  - my_rules.yaml\n```\n\nWhen you use the *levior:* prefix, you can pass a glob-style pattern,\nallowing you to source multiple files in a single include.\n\n```yaml\ninclude:\n  - src: levior:sites/*.yaml\n    with:\n      ...\n```\n\nRules can receive parameters, allowing the creation of more generic rules\nthat can be applied to any URL.\n\n```yaml\nrules:\n  - url: ${URL}\n    gemtext_filters:\n      - filter: levior.filters:uppercased\n        words: ${uwords}\n```\n\nTo pass params to the rule from the config file, set the rule path by setting\nthe *src* attribute, and set the params via the *with* attribute.\n\n```yaml hl_lines=\"2 3\"\ninclude:\n  - src: words_upper.yaml\n    with:\n      URL:\n        - https://example.org/.*.html\n        - https://domain.io\n      uwords:\n        - coffee\n        - milk\n```\n\nThe *puretext* rule keeps only the text content:\n\n```yaml\ninclude:\n  - src: levior:puretext.yaml\n    with:\n      URL:\n        - https://example.org\n        - https://example2.org\n```\n\n### Proxies\n\n#### Default proxy\n\nYou can set the default proxy URL with the *proxy* attribute, whose value\nmust be a proxy URL or a list of proxy URLs, to establish a proxy chain.\nHTTP, Socks4 and Socks5 proxies are supported.\n\nDefining a single proxy:\n\n```yaml\nproxy: socks5://user:password@localhost:9050\n```\n\n```yaml\nproxy: http://127.0.0.1:8090\n```\n\nTo use a proxy chain (Proxy chaining is a technique that allows you to\nuse multiple proxies to access the web anonymously and bypass\ngeo-restrictions), just declare your proxies as a list (the order matters):\n\n```yaml\nproxy:\n  - socks4://127.0.0.1:1081\n  - socks5://localhost:9050\n  - http://10.0.1.2:8090\n```\n\n#### Random proxies\n\nYou can use the OmegaConf resolver called **random** to choose a\nrandom proxy from a predefined list. The resolver will be called\non every request, so this means that a proxy URL will be randomly chosen\nfrom the list for every request:\n\n```yaml\nmy_proxies:\n  - http://10.0.1.2:8090\n  - http://10.0.4.2:8092\n  - http://10.0.8.4:8094\n\nproxy: ${random:${my_proxies}}\n```\n\n#### Setting a proxy for a rule\n\n```yaml\nrules:\n  - regexp: \"https://freebsd.org\"\n    proxy: socks5://localhost:9050\n```\n\n#### Setting a proxy when including another config file\n\nWhen including one or more config files, you can set the proxy that will\nbe used for the included rules:\n\n```yaml\ninclude:\n  - src: levior:sites/*.yaml\n    proxy: http://127.0.0.1:8090\n```\n\n### HTTP headers\n\nIn a rule or at the top of the config file, you can set specific HTTP headers\nthat will be used when making HTTP requests:\n\n```yaml\nhttp_headers:\n  Accept-Language: en-US\n  Accept-Charset: utf-8\n```\n\n### Feeds aggregator\n\nIt is possible to aggregate multiple Atom/RSS web feeds into a single\ntinylog, by setting the rule type to *feeds_aggregator* and defining the\nlist of feeds. Example:\n\n```yaml hl_lines=\"3\"\nrules:\n  - url: '^gemini://localhost/francetv'\n    type: 'feeds_aggregator'\n\n    # \"feeds\" is a dictionary, the key must be the feed's URL, the\n    # dict value is for the feed's options\n    feeds:\n      https://www.francetvinfo.fr/titres.rss: {}\n      https://www.francetvinfo.fr/monde.rss: {}\n      https://www.francetvinfo.fr/culture.rss:\n        enabled: false\n```\n\nWhen you are sourcing a config file that includes aggregation rules,\nyou can enable or disable certain feeds using the parameters:\n\n```yaml hl_lines=\"4 5\"\n  - src: levior:sites/francetvinfo.yaml\n    with:\n      ftvinfo_feeds:\n        culture: true\n        sports: true\n```\n\n### Gemtext filters\n\nIt's possible to run filters on the gemtext content that will be sent to\nthe browser. In your config file, set the *gemtext_filters* property for the\nrule. For example, this will remove any email address link by running\nthe *strip_emailaddrs* function found in the *levior.filters.links* python\nmodule (if you don't specify a function name, it will call the\n*gemtext_filter* function/coroutine in that module by default):\n\n```yaml hl_lines=\"6\"\nurules:\n  - url:\n    - \"https://searx.be/search\"\n    - \"https://lite.duckduckgo.com/lite/search\"\n\n    gemtext_filters:\n      - levior.filters.links:strip_emailaddrs\n      - filter: levior.filters:get_out\n        re:\n          - 'google'\n          - 'stop'\n```\n\nYou can also pass params to your filter. This rule removes all (English)\nwikipedia URLs and PNG image URLs in the final gemtext:\n\n```yaml hl_lines=\"5 6 7\"\nurules:\n  - url: \".*\"\n    gemtext_filters:\n      - filter: levior.filters.links:url_remove\n        urls:\n          - ^https://en.wikipedia.org\n          - \\.png$\n```\n\nYour filter (which can be a function or a coroutine) can return different\nvalue types:\n\n- *boolean*: if your filter returns *True*, that gemtext line will be **removed** (filtered out).\n- [Line](https://gitlab.com/lofidevops/trimgmi/-/blob/main/trimgmi/__init__.py?ref_type=heads#L99) (*trimgmi* class): If you return a *Line* object, it will be used\n  to **replace** the original gemtext line.\n- *list*: If you return a list of *Line* objects, they will be inserted in\n  place\n- *str*: **replace** the original gemtext line with this raw string value\n- *int*: If your filter returns a negative integer, everything after that in\n  the document (including that line) will be removed.\n\nAny other return value type will be ignored.\n\nCheckout [the filters package](https://gitlab.com/cipres/levior/-/tree/master/levior/filters) to see all the available builtin filters.\n\n### OmegaConf resolvers\n\nlevior provides a few OC resolvers (which are like functions called when the\nYAML element is accessed).\n\n#### random\n\nReturns a random item from a list.\n\n```yaml\nmy_proxies:\n  - http://10.0.1.2:8090\n  - http://10.0.4.2:8092\n  - http://10.0.8.4:8094\n\nproxy: ${random:${my_proxies}}\n```\n\n#### ua_roulette\n\n*User Agent roulette*.\n\nReturns a random browser user agent string. Takes no argument.\n\n```yaml\nhttp_user_agent: ${ua_roulette:}\n```\n\n#### custom_ua_roulette\n\n*Custom User Agent roulette*.\n\nReturns a random browser user agent string for specific operating systems,\nbrowsers and browser engines. The parameters are, in this order:\n\n- Operating system list. e.g: [linux, freebsd]\n- Software list (*optional*). e.g: [firefox, chromium]\n- Software engine list (*optional*). e.g: [webkit,blink]\n- Hardware type list (*optional*). e.g: [mobile]\n\n```yaml\nhttp_user_agent: ${custom_ua_roulette:[linux]}\n```\n\n```yaml\nhttp_user_agent: ${custom_ua_roulette:[linux,mac,freebsd],[firefox]}\n```\n\n```yaml\nhttp_user_agent: ${custom_ua_roulette:[linux,freebsd],[],[webkit]}\n```\n\n```yaml\nhttp_user_agent: ${custom_ua_roulette:[linux,windows,mac_os_x],[],[],[mobile]}\n```\n\nSee [the random_user_agent documentation](https://github.com/Luqman-Ud-Din/random_user_agent/blob/master/random_user_agent/params.py) for a list of params.\n\n*Note*: passing invalid parameters will raise a *ValueError* exception.\n\n## Javascript rendering\n\n*Experimental feature*.\n\n*levior* (through the use of\n[requests-html](https://github.com/psf/requests-html) which uses the\n[pyppeteer](https://github.com/pyppeteer/pyppeteer)\nheadless automation library) can render webpages that contain\nJavascript code.\n\nPass **--js** on the command-line to enable Javascript\nrendering. Use **js-force** to always run JS rendering even if no JS scripts\nwere detected on the page.\n\n**Note**: when you run levior with JS rendering for the first time, pyppeteer\nwill download a copy of the browser binary that it requires to run\n(about ~300 Mb of free disk space is required).\n\n## Service modes\n\n- *server*: serves web content as gemtext, via gemini URLs. When you visit levior's\n  gemini URL ([gemini://localhost](gemini://localhost) by default) you'll be\n  asked for a web domain to browse via a gemini input request.\n  You can also simply go to **gemini://localhost/{domain}** in your Gemini\n  browser, for example [gemini://localhost/sr.ht](gemini://localhost/sr.ht)\n  to browse [https://sr.ht](https://sr.ht).\n  The URLs in the HTML pages are rewritten to be routed through the\n  levior server. **This mode is compatible with any Gemini browser.**\n\n- *proxy*: in this mode, *levior* acts as a proxy for http and https URLs\n  and serves pages without rewriting URLs. **To use this mode, you need a\n  Gemini browser that supports http proxies**. Here's a list of browsers\n  supporting proxies:\n  [Gemalaya](https://gemalaya.gitlab.io) (bundles and uses levior in proxy mode\n  by default), [Lagrange](https://gmi.skyjake.fi/lagrange/),\n  [Amfora](https://github.com/makew0rld/amfora),\n  [diohsc](https://hackage.haskell.org/package/diohsc) and\n  [Telescope](https://telescope.omarpolo.com/).\n\nThe allowed modes can be set with the **--mode** (or **-m**) command-line\nargument or with the *mode* setting in the config file. Use **--mode=proxy** to\nrun only as a transparent http proxy, or **--mode=server** to only serve\nrequests made with gemini URLs.\n\nUse **--mode=proxy,server** to handle both request types (this is the default).\n\n## Configuring your Gemini browser to use levior as a proxy\n\n### Lagrange\n\nIn the *File* menu, select *Preferences*, and go to the\n*Network* section. Set the *HTTP proxy* text field to *127.0.0.1:1965*.\nIf you're not running levior on *localhost*, set it\nto levior's listening IP and port.\n\n### Telescope\n\nAs explained in the [docs](https://telescope.omarpolo.com/telescope.1.html),\nedit *~/.config/telescope/config* and add the following:\n\n```\nproxy http via \"gemini://127.0.0.1:1965\"\nproxy https via \"gemini://127.0.0.1:1965\"\n```\n\n## Links\n\nThe **--links** option controls the Gemini links generation mode (this is\nan *md2gemini* option):\n\n- **paragraph** (this is the default): This will result in footnotes being added to the document, and the links for each footnote being added at the end of each paragraph\n- **copy**: Like **paragraph**, but without footnotes\n- **at-end**: The links are added at the very end of the document\n- **off**: Remove all links\n\n```sh\nlevior --links=at-end\nlevior --links=off\n```\n\nOpen your Gemini browser and go to *gemini://localhost* or *//localhost*.\n\n## Mounting ZIM images\n\nYou can also mount ZIM files to be served via the gemini protocol. Once you've configured\na ZIM mountpoint, go to *gemini://localhost/{mountpoint}* (for example:\n*gemini://localhost/wiki_en*). A great source of ZIM archives is the\n[kiwix library](https://library.kiwix.org).\n\nIt's possible to run searches on the ZIM archive's contents. Go to\n*gemini://localhost/{mountpoint}/search*\n(for example: *gemini://localhost/wiki_en/search*), where you'll be prompted\nfor a search query (by default there's a limit of 4096 results, this can be\nchanged via the *search_results_max* option). The *search_path* option\nsets the URL path of the search API:\n\n```yaml\nmount:\n  /wiki_en:\n    type: zim\n    path: ./wikipedia_en_all_mini_2022-03.zim\n    search_path: /\n    search_results_max: 8192\n```\n\nSee the [example config file here](https://gitlab.com/cipres/levior/-/raw/master/examples/levior.zim.yaml).\n\n## Server endpoints\n\n### /\n\nThe homepage lists the links for the main endpoints, the mountpoints and\nthe links to access the aggregated RSS/Atom feeds.\n\n### /goto\n\nWhen accessing */goto*, or */go*, you'll be prompted for a domain name or\na full URL to browse.\n\n### /{domain}\n\nWhen accessing */{domain}*, *levior* will proxy *https://{domain}* to the\nGemini browser. Examples:\n\n```sh\ngemini://localhost/searx.be\ngemini://localhost/gitlab.com/cipres/levior\n```\n\n### /access_log\n\nShows the proxy's access log.\n\n### /cache\n\nLists the objects stored in the cache.\n\n### /graph\n\nRDF graph index\n\n### /graph/search\n\nRDF graph search endpoint\n\n### /search\n\nWhen accessing */search*, you'll be prompted for a search query. Your search\nwill be performed via the *searx* search engine.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpancakesarchitect%2Flevior","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpancakesarchitect%2Flevior","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpancakesarchitect%2Flevior/lists"}