{"id":21654174,"url":"https://github.com/gustavohenrique/link4fun","last_synced_at":"2026-03-10T02:03:41.271Z","repository":{"id":66689916,"uuid":"297160119","full_name":"gustavohenrique/link4fun","owner":"gustavohenrique","description":"URL Shortener, Markdown Editor and Snippet store","archived":false,"fork":false,"pushed_at":"2021-06-11T12:32:37.000Z","size":669,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-11T21:13:03.141Z","etag":null,"topics":["lua","nginx","openresty"],"latest_commit_sha":null,"homepage":"https://link4.fun","language":"CSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gustavohenrique.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-20T20:42:54.000Z","updated_at":"2021-09-03T02:44:14.000Z","dependencies_parsed_at":null,"dependency_job_id":"e642c51b-bd5b-4d52-ac7a-2bc61b4d2fb3","html_url":"https://github.com/gustavohenrique/link4fun","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gustavohenrique/link4fun","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavohenrique%2Flink4fun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavohenrique%2Flink4fun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavohenrique%2Flink4fun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavohenrique%2Flink4fun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gustavohenrique","download_url":"https://codeload.github.com/gustavohenrique/link4fun/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavohenrique%2Flink4fun/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30322637,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T01:36:58.598Z","status":"online","status_checked_at":"2026-03-10T02:00:06.579Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["lua","nginx","openresty"],"created_at":"2024-11-25T08:26:33.869Z","updated_at":"2026-03-10T02:03:36.253Z","avatar_url":"https://github.com/gustavohenrique.png","language":"CSS","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Link4Fun](site/static/images/logo.png)\n===\n\nLink4Fun a PoC using OpenResty (Nginx + Lua). Check it https://link4.fun.\n\nFeatures:\n\n- URL Shortener\n- Markdown Editor with syntax highlight\n- Text Snippet like Pastebin\n- Dark mode according to browser's preference\n- Simple authentication using SHA256 hash password\n\n## How it works?\n\n### Modules\n\n#### URL Shortener\n\nA CSV file saved in `$data_dir/shortener` contains the long URL and the number of hits.  \nLink4Fun receives an ID, read the file with the name equals this ID, increases the hits counter, and redirect to the long URL\n\n#### Markdown Editor\n\nIt uses CodeMirror JS as editor and Marked JS to convert the Markdown syntax to HTML using Javascript.  \nAll files will be saved as raw Markdown in `$data_dir/markdown`. You can add the suffix **.md** in the URL to get the raw data or **.html** to get a formatted Markdown by the server-side (using the Hoedown lib) instead of formated by Marked JS.\n\n#### Text Snippet\n\nYou can format pieces of code using the most used syntaxes supported by the Highlight JS library. All data will be saved in `$data_dir/snippet`.\n\n#### Authentication\n\nThe username and password are defined in the Nginx configuration file. The password must be a SHA256 hash.  \nThere isn't support to sign up and only the authenticated user can edit contents.  \nA hash can be generated running the command:\n\n```sh\necho -ne mypassword | sha256sum\n```\n\n### Organization\n\n```\n.\n├── conf/             # Nginx config files\n├── site/\n│   ├── static/       # images, fonts, css and javascript files\n│   ├── templates/    # HTML files rendered by lua\n├── lua/\n│   ├── main.lua      # where the magic begins. it instanciate dependencies and inject them in the other modules\n│   ├── app/          # application modules\n│   ├── lib/          # application libraries and OpenResty modules\n├── lxd/              # tools to help me to configure a LXD container\n```\n\n## Setup\n\n### Docker\n\n```sh\n# make docker\ndocker build . -t=gustavohenrique/link4fun:alpine\ndocker run -d --name link4fun -p 8000:80 gustavohenrique/link4fun:alpine\nopen http://localhost:8000\n```\n\nUse an external volume to keep saved data:\n\n```sh\nmkdir -p ~/data/{shortener,snippet,markdown}\ndocker run -d --name link4fun -v $HOME/data:/var/www/data -p 8000:80 gustavohenrique/link4fun:alpine\n```\n\n### Ubuntu Linux\n\nOpenResty is a web platform that integrates the Nginx core with LuaJit.  \nFollow the instructions in https://openresty.org/en/installation.html or use\nthe provided script:\n\n```sh\ncd lxd\nbash install-openresty-ubuntu.sh\n```\n\nAfter install, replace the original Nginx configuration with our custom configuration:\n\n```sh\nrm -rf /usr/local/openresty/nginx/conf\nln -snf $PWD/link4fun/conf /usr/local/openresty/nginx/conf\nln -snf $PWD/link4fun/conf/development.conf /usr/local/openresty/nginx/conf/site.conf\n```\n\nThe `/var/www/data` is the place where all data will be saved. The user in `nginx.conf` must be the owner of `/var/www`.\n\n```sh\nsudo mkdir -p /var/www/data/{shortener,markdown,snippet}\nsudo mkdir /var/log/nginx\n\n# ubuntu is the user defined in link4fun/conf/nginx.conf\nsudo chown ubuntu:ubuntu -Rf /var/www\nsudo chown ubuntu:ubuntu -Rf /var/log/nginx\n\nsudo ln -snf $PWD/link4fun/lua /var/www/lua\nsudo ln -sn  $PWD/link4fun/site /var/www/site\n```\n\n#### Optional Harderning\n\n```sh\n# Kernel params\nsudo tee -a /etc/sysctl.conf \u003c\u003cEOF\nfs.file-max=50000                   # the number of files that a process can open concurrently\nnet.ipv4.tcp_max_syn_backlog = 4096 # number of connection requests did not receive an ack from client\nnet.core.somaxconn = 4096 # limit of socket listen() backlog\n\n# increase the write-buffer-space allocatable\nnet.ipv4.tcp_wmem = 4096 65536 524288\nnet.core.wmem_max = 16384\n\nnet.ipv4.tcp_abort_on_overflow = 1\nnet.ipv4.tcp_max_tw_buckets = 1440000\nnet.core.wmem_default = 8388608\nnet.core.rmem_default = 8388608\nnet.ipv4.tcp_sack = 1\nnet.ipv4.tcp_window_scaling = 1\nnet.ipv4.tcp_fin_timeout = 15\nnet.ipv4.tcp_keepalive_intvl = 30\nnet.ipv4.tcp_tw_reuse = 1\nnet.ipv4.tcp_moderate_rcvbuf = 1\nnet.core.rmem_max = 134217728\nnet.core.wmem_max = 134217728\nnet.ipv4.tcp_mem  = 134217728 134217728 134217728\nnet.ipv4.tcp_rmem = 4096 277750 134217728\nnet.ipv4.tcp_wmem = 4096 277750 134217728\nnet.core.netdev_max_backlog = 300000\nEOF\n\n# File descriptors\nsudo tee -a /etc/security/limits.conf \u003c\u003cEOF\nubuntu soft nofile 65535\nubuntu hard nofile 97816\nEOF\n\n# Edit /lib/systemd/system/openresty.service\n# LimitNOFILE=65535\n# LimitNOFILESoft=97816\n# If OpenResty is running: prlimit --pid \u003copenresty pid\u003e --nofile=65535:97816\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgustavohenrique%2Flink4fun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgustavohenrique%2Flink4fun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgustavohenrique%2Flink4fun/lists"}