{"id":13770782,"url":"https://github.com/bunburya/apogee","last_synced_at":"2025-05-11T03:32:53.985Z","repository":{"id":141955793,"uuid":"359929882","full_name":"bunburya/apogee","owner":"bunburya","description":"A Gemini server written in Kotlin (WIP)","archived":false,"fork":false,"pushed_at":"2023-12-26T04:23:38.000Z","size":245,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-11-17T06:40:27.009Z","etag":null,"topics":["gemini","gemini-protocol","gemini-protocol-server","kotlin","netty","server"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","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/bunburya.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2021-04-20T19:31:05.000Z","updated_at":"2023-12-27T07:45:38.000Z","dependencies_parsed_at":"2023-12-26T05:25:11.488Z","dependency_job_id":"f96950fa-1174-4113-ad73-76a2aeee4440","html_url":"https://github.com/bunburya/apogee","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bunburya%2Fapogee","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bunburya%2Fapogee/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bunburya%2Fapogee/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bunburya%2Fapogee/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bunburya","download_url":"https://codeload.github.com/bunburya/apogee/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253514352,"owners_count":21920327,"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":["gemini","gemini-protocol","gemini-protocol-server","kotlin","netty","server"],"created_at":"2024-08-03T17:00:42.072Z","updated_at":"2025-05-11T03:32:53.460Z","avatar_url":"https://github.com/bunburya.png","language":"Kotlin","funding_links":[],"categories":["Servers"],"sub_categories":["Graphical"],"readme":"# Apogee, a Gemini server\n\nApogee is a server for the [Gemini protocol](https://gemini.circumlunar.space/), written in Kotlin.\n\n## Features\n\nApogee currently\nhas support for the following features:\n\n- Static file serving.\n- Redirections.\n- Client authentication.\n- CGI and SCGI.\n\n## Dependencies\n\nApogee runs on a JVM, so some implementation is required (it was developed and tested on \n[OpenJDK](https://openjdk.java.net/)). Java 8 is the minimum supported version.\n\nOther than that, Apogee depends on the following external libraries:\n- [Netty](https://netty.io/) to handle socket connections. \n- [TOML4J](https://github.com/mwanji/toml4j) to handle configuration file parsing.\n- [kotlinx-cli](https://github.com/Kotlin/kotlinx-cli) to handle command line options.\n\nApogee has been developed and tested for Linux; Windows is not officially supported, though if you try to run it on\nWindows and encounter a specific problem please feel free to file an issue.\n\n## Installation\n\nCurrently, the easiest way to run Apogee is to clone the Git repository:\n\n```commandline\ngit clone https://github.com/bunburya/apogee.git\n```\n\nThen, from the cloned directory, run:\n\n```shell\n./gradlew run --args=\"--config /path/to/config.toml\"\n```\n\nAlternatively, you can build a shell script:\n\n```shell\n./gradlew build -x test\n```\n\nThis builds Apogee without running the tests (some of which are integration tests that depend on an already running\ninstance). The shell script can be found in the `build/distributions` directory (in the `bin` subdirectory of the\ndirectory you get when you extract the zip or tar archive). You can then initialise Apogee using the following command\n(make sure the `apogee` shell script is in your shell path):\n\n```shell\napogee --config /path/to/config.toml\n```\n\n## Configuration\n\nApogee is configured through a single [TOML](https://toml.io/en/) file. This section will discuss the main configuration\noptions. In the `src/main/resources` directory you will find an example config file, populated with default values\nwhere appropriate.\n\n**NOTE:** Configuration of certain features, such as redirection, is done via key-value pairs stored in tables,\nwhere the keys are regex patterns against which the path is compared. The first pattern which matches the path will be\nused to determine the appropriate value. Tables in TOML files are not guaranteed to be in any particular order.\nTherefore, you should be careful to ensure that patterns are mutually exclusive, as there is no guarantee as to what\norder they will be checked.\n\n### Basic settings\n\nThese are settings to control the basic behaviour of Apogee.\n\n|Option name |Description | Default value|\n|---|---|---|\n|PORT|The port on which Apogee will listen for requests.|1965|\n|HOSTNAME|The name of the host at which Apogee will listen for requests.|localhost|\n|CERT_FILE|The location of the file containing the server's SSL certificate, in PEM format.|cert.pem|\n|KEY_FILE|The location of the file containing the server's SSL key, in PEM format.|key.pem|\n|DOCUMENT_ROOT|The location of the directory containing the files to be served by Apogee.|/var/gemini/|\n|ACCESS_FILE|Where to log access attempts.|null (logs to standard error)|\n|LOG_FILE|Where to store general logs.|null (logs to standard error)|\n|LOG_LEVEL|How severe a log message must be in order to be logged to LOG_FILE. This should correspond to the levels used by the [java.util.logging](https://docs.oracle.com/javase/7/docs/technotes/guides/logging/overview.html#a1.2) library, ie, it should be one of \"SEVERE\", \"WARNING\", \"INFO\", \"CONFIG\", \"FINE\", \"FINER\" or \"FINEST\".|WARNING|\n\n### Static files\n\nThese settings control certain aspects of how Apogee serves static files.\n\n|Option name |Description | Default value|\n|---|---|---|\n|GEMINI_EXT|The file extension that Apogee will interpret as indicating the \"text/gemini\" MIME type.|gmi|\n|INDEX_FILE|The name of the file that Apogee will attempt to serve if a request corresponds to a directory. If no index file is present, Apogee will display a basic index which lists files in the directory.|index.gmi|\n|DIR_SORT_METHOD|*(Not yet implemented)* Where Apogee auto-generates an index for a directory, how to sort the files in the directory.|NAME|\n\nThe `MIME_OVERRIDES` section allows you to customise the MIME type that is sent where a filename corresponds to a given\nregular expression.\n\n### Dynamic content\n\nApogee currently supports dynamic content through the CGI and SCGI protocols. It is intended to also support FastCGI in\nthe future.\n\nThe `CGI_TIMEOUT` option governs how many seconds Apogee should wait for a response from a process before returning an\nerror response. It defaults to 10.\n\nThe `CGI_PATHS` option should be an array of filesystem paths to directories. Where a request corresponds to a file in\none of these directories, Apogee will attempt to run that file as a script and return the standard output of that script\nto the client.\n\nThe `SCGI_PATHS` section is a table mapping (relative) URL prefixes to filesystem paths to Unix domain sockets. Where a\nrequest contains one of the specified prefixes, it will be encoded according to the SCGI protocol and written to the \nrelevant socket. It will then listen on the socket and return any output to the client. In the future it is intended to\nsupport network sockets in addition to Unix domain sockets.\n\nBoth CGI and SCGI scripts are responsible for sending their own headers (eg, `20 text/gemini\\r\\n`).\n\nThe following are the main variables passed to applications over CGI/SCGI:\n\n|Variable name |Description |Protocol|\n|---|---|---|\n|GATEWAY_INTERFACE|The name of the gateway interface used, followed, if applicable, by a \"/\" and the version number, eg, `CGI/1.1` or `SCGI`.|CGI/SCGI|\n|SERVER_NAME|The hostname of the server on which Apogee is running.|CGI/SCGI|\n|SERVER_PORT|The port on which Apogee is listening.|CGI/SCGI|\n|SERVER_PROTOCOL|The protocol the server is using - always \"GEMINI\".|CGI/SCGI|\n|SERVER_SOFTWARE|The software running the server - always \"APOGEE\".|CGI/SCGI|\n|REMOTE_ADDR|The IP address from which the request originated.|CGI/SCGI|\n|SCRIPT_PATH|The part of the request path corresponding to the relevant script. For CGI, this is the part of the path that corresponds to the CGI script to be run; for SCGI, it corresponds to the prefix specified in the config file.|CGI/SCGI|\n|PATH_INFO|The part of the request path after SCRIPT_PATH (excluding any query string).|CGI/SCGI|\n|QUERY_STRING|You guessed it - the query string, if any, specified in the request.|CGI/SCGI|\n|REQUEST_METHOD|Always an empty string, as Gemini does not support different request methods.|CGI/SCGI|\n|TLS_CLIENT_HASH|If a client certificate is provided, the SHA256 hash of that certificate. Not present otherwise.|CGI/SCGI|\n|TLS_CLIENT_ISSUER_DN|If a client certificate is provided, the distinguished name of the certificate issuer. Not present otherwise.|CGI/SCGI|\n|TLS_CLIENT_SUBJECT_DN|If a client certificate is provided, the distinguished name of the certificate subject. Not present otherwise.|CGI/SCGI|\n|AUTH_TYPE|If a client certificate is provided, \"Certificate\". Not present otherwise.|CGI/SCGI|\n|SCGI|Always \"1\", as required by the SCGI protocol.|SCGI|\n|CONTENT_LENGTH|The length of the request body - this will always be 0, as Gemini does not permit request bodies.|SCGI|\n\n### Redirects\n\nYou can tell Apogee to redirect certain paths using the `TEMP_REDIRECTS` and `PERM_REDIRECTS` sections of the config\nfile. Each entry in these sections should map a regular expression, against which a path will be checked, to the path to\nredirect to. Requests matched against entries in the `TEMP_REDIRECTS` section will receive a temporary redirect\nresponse (status code 30). Requests matched against entries in the `PERM_REDIRECTS` section will receive a permanent\nredirect response (status code 31).\n\n### Client authorisation\n\nApogee has support for client authentication using client-side SSL certificates. The `CLIENT_CERT_ZONES` section should\nbe a table mapping regular expressions to lists of supported client certificate SHA256 fingerprints. Client\nauthentication is done immediately after the request is received by the server, so redirections, dynamic content, etc,\nwill not be handled unless a request is authenticated (if necessary).\n\n## Obligatory security warning\n\nRemember that Apogee is still a work in progress and should not be considered to be completely secure. Use at your own risk. It is your responsibility to ensure that your server, and any scripts called by it, are secure. If you do discover any vulnerabilities or other issues with Apogee, please file an issue.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbunburya%2Fapogee","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbunburya%2Fapogee","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbunburya%2Fapogee/lists"}