{"id":15115401,"url":"https://github.com/sstark/gjfy","last_synced_at":"2025-04-23T13:05:37.647Z","repository":{"id":52195386,"uuid":"73897538","full_name":"sstark/gjfy","owner":"sstark","description":"gjfy is a standalone one-time link server. Use it to securely share secrets.","archived":false,"fork":false,"pushed_at":"2023-07-10T19:03:05.000Z","size":94,"stargazers_count":57,"open_issues_count":0,"forks_count":8,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-01-18T03:31:15.843Z","etag":null,"topics":["cloudless","link","one-time","password","private","secret","self-hosted","server","standalone","web"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sstark.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.TXT","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":"2016-11-16T08:03:18.000Z","updated_at":"2024-07-22T01:49:38.000Z","dependencies_parsed_at":"2024-06-18T23:59:47.429Z","dependency_job_id":"a37ee0f2-0b66-406e-bdf6-d52a0763b268","html_url":"https://github.com/sstark/gjfy","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sstark%2Fgjfy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sstark%2Fgjfy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sstark%2Fgjfy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sstark%2Fgjfy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sstark","download_url":"https://codeload.github.com/sstark/gjfy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237794525,"owners_count":19367428,"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":["cloudless","link","one-time","password","private","secret","self-hosted","server","standalone","web"],"created_at":"2024-09-26T01:43:49.767Z","updated_at":"2025-02-08T10:34:01.800Z","avatar_url":"https://github.com/sstark.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"![gjfy](https://raw.githubusercontent.com/sstark/gjfy/master/logo.png)\n\none time link server\n====================\n\nWhat does it do?\n----------------\n\ngjfy is a single binary, standalone web server with only one purpose: Create\nlinks that automatically disappear once clicked. On first click it will show a\n\"secret\", for instance a password that somebody wants to send to someone.\n\nThe idea is that if the original receiver finds the link invalid, they know\nthat the secret was intercepted by a third party and the sender can reset the\npassword. This does not protect against eavesdropping attacks, for this you\nneed a TLS connection.\n\nThere is no persistency: If the server process ends, all secrets are gone.\n\nPlease be careful: Using a tool like gjfy is only advised when all other\noptions are even less secure (mail, e-mail, phone). In any case, if you send a\npassword, the receiver should be told to change it as soon as possible.\n\nWhat makes it different?\n------------------------\n\nThere are other tools available that do similar things. However, usually those\ninvolve installing lots of dependencies or web frameworks and often require\nsetting up a database. Some of them are even offering a hosted service, so\nyou would be handing your secrets to a third party.\n\nGjfy does not need any of this: it is a completely self-contained and\non-premise system.\n\nProbably the most notable difference is that secrets are only kept in memory.\nThey are never written into a database or a file. So it can never happen that,\nbecause of a program bug or sysadmin mistake, the secrets are left on the disk.\nHowever, it is possible that the operating system will write part of the\nprogram memory into swap temporarily, which is not easy to avoid.\n\nThe author believes that tools like this should not load assets from external\nsources and also that no javascript should be used. Gjfy will never do that and\ninstead try to be as simple and privacy respecting as possible.\n\n\nFeatures\n--------\n\n  - Everything in a single binary\n  - No web server or application server needed\n  - No database needed\n  - No persistence\n  - No javascript\n  - Simple json API (demo client included)\n  - Simple html user interface\n  - The CSS styling, logo and user message can be customised\n  - Simple token based authentication\n  - Supports IPv6, HTTP2, TLS\n  - Email notification\n\nBuilding\n--------\n\nA precompiled binary is provided with each release. It is also easy to build\ngjfy yourself, in case you prefer that:\n\nIf you do not have a go environment installed already, install it from your\nlinux distribution repository (e. g. `apt-get install golang-go`) or download\nit from the [go home page](https://golang.org/dl/).\n\nDownload the code and run \"go build\", it will create a single binary file for\neasy deployment.\n\n`go get github.com/sstark/gjfy` will also work.\n\nInstallation\n------------\n\nCreate a directory, e. g. `/usr/local/gjfy`. Then copy the following files to it:\n\n  - gjfy (the binary you just built)\u003csup\u003e1\u003c/sup\u003e\n  - auth.db\n  - logo.png\n  - custom.css\n\nFor integration into the various system management environments like upstart or\nsystemd, check the init/ subdirectory for examples.\n\n\u003csup\u003e1\u003c/sup\u003eIf you installed using \"go get\" the binary will be located at\n`$GOPATH/bin/gjfy`, while the rest of the files will be under `$GOPATH/src/github.com/sstark/gjfy`\n\nRunning\n-------\n\nChoose the IP address and port gjfy listens on with the `-listen` parameter.\n\nExamples:\n\n    gjfy -listen '0.0.0.0:1234'    # listen on all IPv4 addresses\n    gjfy -listen '[::1]:4123'      # listen on localhost, IPv6 only\n    gjfy -listen ':6234'           # listen on all addresses, IPv4 and IPv6\n\nTo tell gjfy its name as seen by users of the service, use the `-urlbase` parameter like so:\n\n    gjfy -urlbase 'https://gjfy.example.org'\n    gjfy -urlbase 'https://gjfy.example.org:4123'\n\nTo use TLS security add the `-tls` switch:\n\n    gjfy -tls\n\nThe scheme will automatically switch to https unless you set urlbase. Before\nyou can turn on tls you must create a certificate file called `gjfy.crt` and a\nkey file called `gjfy.key`.\n\nUse `gjfy -help` for help.\n\nOptions\n-------\n\nCustom CSS styling can by applied by placing a file \"custom.css\" in either\n`/etc/gjfy/custom.css` or `$PWD/custom.css`.\n\nAn authentication token database should placed in either `/etc/gjfy/auth.db` or\n`$PWD/auth.db`. An example file is distributed with the software. New secrets\ncan only be created with a valid auth token in the POST request.\n\nIf you are using TLS mode you need to put in place either `/etc/gjfy/gjfy.crt`\nor `$PWD/gjfy.crt`. Same applies to the key file `gjfy.key`.\n\nThe logo.png can be replaced by a custom logo if needed. (It must be png)\n\nYou may create a file `userMessageView.txt` that will contain the message the\nuser sees when clicking on the link. It will replace the default message. HTML\ncan not be used.\n\n`$PWD/\u003cfile\u003e` will take precedence over `/etc/gjfy/\u003cfile\u003e` for above options.\n\nTo trigger reloading of auth.db, logo.png, custom.css or userMessageView.txt\nyou can send SIGHUP to the gjfy process. The TLS certificate or key won't be\nreloaded this way.\n\nAuthentication\n--------------\n\ngjfy has a very simple authentication model. Requests that add tokens are\nrequired to carry an *auth_token* in their json data. This *auth_token* is\nlooked up in the file `auth.db` and the corresponding email address used for\nfurther processing and notification. If gjfy does not find the provided\nauth_token, it will reject the request.\n\nAuthentication is only for adding new secrets. It does not give access to the\nsecrets itself.\n\nThis authentication model has some downsides and should probably be replaced by\nsomething better. For now just keep in mind that every user in auth.db needs to\nhave an individual auth_token, because it is used to identify the \"user\".\n\nTo add an account to `auth.db`, simply edit it using your favorite editor and\nadd a section to the json list that is contained in it, like this:\n\n    {\n        \"token\": \"thesecretauthtoken\",\n        \"email\": \"test@example.org\"\n    }\n\nAfterwards send gjfy a hangup signal (`killall -HUP gjfy`) to make it reload\nthe file. In the logfile you will be informed about success or failure.\n\nUsage\n-----\n\nCurrently the only way to create new secrets is by using the json API. An\nexample client (gjfy-post) is included. A basic request looks like this:\n\n    {\"auth_token\":\"g4uhg3iu4h5i3u4\",\"secret\":\"someSecret\"}\n\nBy sending this to `/api/v1/new` you create a new URL which is a hash over that\njson structure. The reply from the server will tell you this link in both, a\nuser friendly version and in an API version. Invocation of that link will\nimmediately lead to deletion of the secret in the server. However, there is an\nexception: you can post a `\"max_clicks\":n` variable along with the json and it\nwill allow up to `n` clicks.\n\nThe authentication token sent with the request will not be stored in the\nserver. Instead, the associated email address will be stored with the secret,\nso it can be used for email notifications (see below).\n\nA timeout can be set by including `\"valid_for:n\"` in the request. The secret\nwill become invalid after n days, even if not clicked. The default timeout is 7\ndays.\n\nEmail notifications\n-------------------\n\nTo get notified if somebody uses the one time link, add the `-notify` flag to\nthe gjfy command line. gjfy will use the email address associated with the\nauthentication token that was used when the secret was generated.\n\nThis requires that the email sub system of the server where gjfy is running is\nconfigured properly. In principle, if it is possible to send an email using the\n`mail` command as the gjfy user, email notifications from gjfy should also\nwork.\n\nBy default, email notification is not enabled.\n\ngjfy-post\n---------\n\ngjfy-post is a demonstration client using bash, curl and jq.\n\n    usage: ./gjfy-post \u003cauthtoken\u003e \u003csecret\u003e [maxclicks]\n\nRequired arguments are authtoken and the secret itself. Please note that\nproviding the secret this way makes it readable in the system process listing!\n\nThe client can be downloaded from the running server by using the URL\n\n    /gjfy-post\n\nWhich is also linked from the root page (\"/\").\n\nYou can change the default URL for gjfy-post by setting the environment\nvariable `GJFY_POSTURL`. If you downloaded gify-post via the URL, it will\nhave the correct URL already configured in the script.\n\nFAQ\n---\n\nQ: How do you pronounce gjfy?\n\nA: It is pronounced like \"jiffy\".\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsstark%2Fgjfy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsstark%2Fgjfy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsstark%2Fgjfy/lists"}