Skip to content

Instantly share code, notes, and snippets.

@brettpetch
Last active May 9, 2022 21:48
Show Gist options
  • Save brettpetch/e34ccf8a0335f7e6b726846789b63f11 to your computer and use it in GitHub Desktop.
Save brettpetch/e34ccf8a0335f7e6b726846789b63f11 to your computer and use it in GitHub Desktop.
Kutt Installation

Kutt Installation

Introduction

Kutt is a modern URL shortener with support for custom domains. Shorten URLs, manage your links and view the click rate statistics.

Key Features

  • Free and open source.
  • Custom domain support.
  • Custom URLs for shortened links
  • Set password for links.
  • Set description for links.
  • Expiration time for links.
  • Private statistics for shortened URLs.
  • View, edit, delete and manage your links.
  • Admin account to view, delete and ban links.
  • Ability to disable registration and anonymous link creation for private use.
  • RESTful API.

Configuration

For the minimal configuration the following settings have to be changed in the .env-file:

  • DEFAULT_DOMAIN: The domain of your kutt instance
  • DB_: The DB credentials (when you use docker-compose you can skip these)
  • ADMIN_EMAILS: A comma-separated list of the administrator-accounts
  • RECAPTCHA_: Enter your credentials to use reCaptchas or delete this setting if you don't want to use it
  • MAIL_: Enter the SMTP-server's credentials (The experience shows SSL works better than STARTTLS; The mail config is required to easily create accounts, see this comment how it can be done manually)
  • REPORT_EMAIL: Kutt offers a form to report malicious links which are sent to this mail-address

Getting Going

Prerequisites:

  • Docker
  • 2 beers
  • A bit of nginx know-how

Getting Things into Place

mkdir -p /opt/kutt/

curl -sL "https://gist.github.com/brettpetch/e34ccf8a0335f7e6b726846789b63f11/raw/f245ba5c5866e007d3fb34afa36ea9fa49be1424/docker-compose.yml" -o /opt/kutt/docker-compose.yml

curl -sL "https://gist.github.com/brettpetch/e34ccf8a0335f7e6b726846789b63f11/raw/f245ba5c5866e007d3fb34afa36ea9fa49be1424/.env" -o /opt/kutt/.env

cd /opt/kutt/

# Take this time to modify the files to the above.

Starting the Service

cd /opt/kutt/
docker-compose up -d

Transforming it into a real service

! Important: make sure that the docker-compose path is correct! You can verify this by doing which docker-compose]

# kutt.service
[Unit]
Description=Kutt
After=docker.service
Requires=docker.service
StartLimitBurst=3
StartLimitIntervalSec=30
 
[Service]
RestartSec=5
TimeoutStartSec=0
Restart=on-failure
WorkingDirectory=/opt/kutt
EnvironmentFile=/opt/kutt/.env
# Compose up
ExecStart=/usr/local/bin/docker-compose -f /opt/kutt/docker-compose.yml up

ExecStop=/usr/local/bin/docker-compose -f /opt/kutt/docker-compose.yml stop

ExecReload=/usr/local/bin/docker-compose -f /opt/kutt/docker-compose.yml pull --quiet --ignore-pull-failures
ExecReload=/usr/local/bin/docker-compose -f /opt/kutt/docker-compose.yml up -d

[Install]
WantedBy=multi-user.target

systemctl enable --now kutt.service

Getting your nginx config right

Alert! This nginx config was written for Swizzin installs! If you are not running swizzin, make sure you read the Official Documentation

  1. Generate your SSL certificates using whatever method you might use. (I recommend acme.sh)
  2. curl -sL "https://gist.github.com/brettpetch/e34ccf8a0335f7e6b726846789b63f11/raw/f245ba5c5866e007d3fb34afa36ea9fa49be1424/kutt.conf" -o /etc/nginx/sites-enabled/kutt.conf
  3. nano /etc/nginx/sites-enabled/kutt.conf
  4. Get your stuff edited the way you need it.
  5. nginx -t to test your configuration
  6. nginx -s reload to apply your changes (only run if test succeeds).

Go to your domain you setup, sign up, create your account and get after it.

/b

# App port to run on
PORT=3000
# The name of the site where Kutt is hosted
SITE_NAME=your.domain
# The domain that this website is on
DEFAULT_DOMAIN=your.domain
# Generated link length
LINK_LENGTH=6
# Postgres database credential details
DB_HOST=postgres
DB_PORT=5432
DB_NAME=postgres
DB_USER=
DB_PASSWORD=
DB_SSL=false
# Redis host and port
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=
# Disable registration
DISALLOW_REGISTRATION=false
# Disable anonymous link creation
DISALLOW_ANONYMOUS_LINKS=true
# The daily limit for each user
USER_LIMIT_PER_DAY=200
# Create a cooldown for non-logged in users in minutes
# Set 0 to disable
NON_USER_COOLDOWN=0
# Max number of visits for each link to have detailed stats
DEFAULT_MAX_STATS_PER_LINK=5000
# Use HTTPS for links with custom domain
CUSTOM_DOMAIN_USE_HTTPS=true
# A passphrase to encrypt JWT. Use a long and secure key.
JWT_SECRET=
# Admin emails so they can access admin actions on settings page
# Comma seperated
ADMIN_EMAILS=
# Invisible reCaptcha secret key
# Create one in https://www.google.com/recaptcha/intro/
#RECAPTCHA_SITE_KEY=
#RECAPTCHA_SECRET_KEY=
# Google Cloud API to prevent from users from submitting malware URLs.
# Get it from https://developers.google.com/safe-browsing/v4/get-started
GOOGLE_SAFE_BROWSING_KEY=
# Google Analytics tracking ID for universal analytics.
# Example: UA-XXXX-XX
GOOGLE_ANALYTICS=
GOOGLE_ANALYTICS_UNIVERSAL=
# Google Analytics tracking ID for universal analytics
# This one is used for links
# GOOGLE_ANALYTICS_UNIVERSAL=
# Your email host details to use to send verification emails.
# More info on http://nodemailer.com/
# Mail from example "Kutt <[email protected]>". Leave empty to use MAIL_USER
MAIL_HOST=
MAIL_PORT=465
MAIL_SECURE=true
MAIL_USER=
MAIL_FROM=
MAIL_PASSWORD=
# The email address that will receive submitted reports.
REPORT_EMAIL=
# Support email to show on the app
CONTACT_EMAIL=
version: "3"
services:
kutt:
image: kutt/kutt
depends_on:
- postgres
- redis
command: ["./wait-for-it.sh", "postgres:5432", "--", "npm", "start"]
ports:
- "127.0.0.1:4621:3000"
env_file:
- .env
environment:
DB_HOST: postgres
DB_NAME: kutt
DB_USER: youruser
DB_PASSWORD: somepassword
REDIS_HOST: redis
redis:
image: redis:6.0-alpine
volumes:
- redis_data:/data
postgres:
image: postgres:12-alpine
environment:
POSTGRES_USER: youruser
POSTGRES_PASSWORD: somepassword
POSTGRES_DB: kutt
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
redis_data:
postgres_data:
proxy_cache_path /var/cache/nginx/kutt levels=1:2 keys_zone=kutt:10m max_size=10g
inactive=60m use_temp_path=off;
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name brr.tf;
ssl_certificate /etc/nginx/ssl/mylink.sh/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/mylink.sh/key.pem;
include snippets/ssl-params.conf;
client_max_body_size 128M;
server_tokens off;
add_header Early-Data $ssl_early_data;
proxy_set_header Early-Data $ssl_early_data;
include snippets/error_pages.conf;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
location / {
proxy_pass http://127.0.0.1:4621;
proxy_cache kutt;
proxy_cache_revalidate on;
proxy_cache_min_uses 3;
proxy_cache_background_update on;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_lock on;
proxy_http_version 1.1;
}
location /api/url/sharex {
proxy_pass http://localhost:4621/api/url/submit;
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Content-Type application/json;
proxy_set_body $http_target;
}
location ~ /\.ht {
deny all;
}
gzip on;
gzip_http_version 1.1;
gzip_vary on;
gzip_comp_level 6;
gzip_proxied any;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/javascript;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment