1
0
Fork 0
mirror of https://github.com/SinTan1729/chhoto-url synced 2025-04-28 11:56:52 -05:00

Compare commits

...

19 commits
5.6.3 ... main

Author SHA1 Message Date
bbf5811e13
build: Bumped version to 5.7.1 2025-04-23 23:57:50 -05:00
efc2b03415
docs: Change wording for donations 2025-04-23 16:10:37 -05:00
3aa8884676
docs: Small changes in the README 2025-04-23 16:07:32 -05:00
084334cd11
fix: Better response on error when shortlink is not provided 2025-04-23 15:45:41 -05:00
4eb88f3beb
chg: Match using rusqlite errors instead of strings 2025-04-23 15:23:34 -05:00
c23fcdc9bd
chg: Properly validate error types 2025-04-21 22:20:11 -05:00
21f76f2962
chg: No need to print public uri with port when custom uri is passed 2025-04-21 12:51:00 -05:00
e8af830527
build: Bumped version to 5.7.0 2025-04-21 12:43:05 -05:00
fc2c24d731
build: Updated deps 2025-04-21 12:40:21 -05:00
Sayantan Santra
a170954232
Merge pull request #53 from magnusja/main
Create UNIQUE INDEX on short URL
2025-04-19 20:07:01 -05:00
e39578fa02
chg: Modify shortlink validation logic to utilize the INDEX
It's no longer necessary to separately validate uniqueness
since the UNIQUE INDEX does that for us already.
2025-04-19 20:04:56 -05:00
88ddb4299a
chg: Move the uniqueness validation to the INDEX 2025-04-19 19:31:43 -05:00
Magnus
b2bc2c450b add unique constraint and create index on short URL 2025-04-18 20:26:29 +02:00
Sayantan Santra
d198135144
Merge pull request #48 from ronnyworm/add-helm-chart
add helm chart and add instructions for its usage in README
2025-04-10 15:03:07 -05:00
b838a6e027
new: Added disable_frontend to variables in helm-chart 2025-04-10 15:01:50 -05:00
Ronny Worm
0897b6b63b add other options from docker-compose 2025-04-10 21:46:39 +02:00
97b56c40ae
docs: Added instructions for disabling the frontend 2025-04-10 14:17:22 -05:00
2c8f47c0cb
new: Ability to disable frontend 2025-04-10 12:45:49 -05:00
Ronny Worm
63020b2c24 add helm chart and add intructions for its usage in README 2025-03-23 21:55:40 +01:00
18 changed files with 312 additions and 85 deletions

1
.gitignore vendored
View file

@ -10,3 +10,4 @@ urls.sqlite
.env
cookie*
.idea/
.DS_Store

View file

@ -24,7 +24,7 @@ docker-test: docker-local docker-stop
docker run -p ${PORT}:${PORT} --name chhoto-url -e password="${PASSWORD}" -e public_mode="${PUBLIC_MODE}" \
-e site_url="${SITE_URL}" -e db_url="${DB_URL}" -e redirect_method="${REDIRECT_METHOD}" -e port="${PORT}"\
-e slug_style="${SLUG_STYLE}" -e slug_length="${SLUG_LENGTH}" -e cache_control_header="${CACHE_CONTROL_HEADER}"\
-e api_key="${API_KEY}"\
-e api_key="${API_KEY}" -e disable_frontend="${DISABLE_FRONTEND}"\
-d chhoto-url
docker logs chhoto-url -f

View file

@ -38,21 +38,22 @@ for small. URL means, well... URL. So the name simply means Small URL.
# Features
- Shortens URLs of any length to a randomly generated link.
- (Optional) Allows you to specify the shortened URL instead of the generated
one. (It's surprisingly missing in a surprising number of alternatives.)
one. (It's missing in a surprising number of alternatives.)
- Opening the shortened URL in your browser will instantly redirect you
to the correct long URL. (So no stupid redirecting pages.)
to the correct long URL. (So no stupid redirection pages.)
- Super lightweight and snappy. (The docker image is only ~6MB and RAM uasge
stays under 5MB under normal use.)
- Counts number of hits for each short link in a privacy respecting way
i.e. only the hit is recorded, and nothing else.
- Has a mobile friendly UI, and automatic dark mode.
- Has a public mode, where anyone can add links without authentication. Deleting
or listing available links will need admin access using the password.
or listing available links will need admin access using the password. It's also
possible to completely disable the frontend.
- Allows setting the URL of your website, in case you want to conveniently
generate short links locally.
- Links are stored in an SQLite database.
- Available as a Docker container.
- Backend written in Rust using [Actix](https://actix.rs/), frontend
- Available as a Docker container with a provided compose file.
- Backend written in Rust using [Actix](https://actix.rs/), and frontend
written in plain HTML and vanilla JS, using [Pure CSS](https://purecss.io/)
for styling.
- Uses very basic authentication using a provided password. It's not encrypted in transport.
@ -60,17 +61,16 @@ for small. URL means, well... URL. So the name simply means Small URL.
encrypt the connection by SSL.
# Bloat that will not be implemented
- Tracking or spying of any kind. The only logs that still exist are
- **Tracking or spying of any kind.** The only logs that still exist are
errors printed to stderr and the basic logging (only warnings) provided by the
[`env_logger`](https://crates.io/crates/env_logger) crate.
- User management. If you need a shortener for your whole organization, either
- **User management.** If you need a shortener for your whole organization, either
run separate containers for everyone or use something else.
- Cookies, newsletters, "we value your privacy" popups or any of the multiple
- **Cookies, newsletters**, "we value your privacy" popups or any of the multiple
other ways modern web shows how anti-user it is. We all hate those, and they're
not needed here.
- Paywalls or messages begging for donations. If you want to support me (for
whatever reason), you can message me through GitHub issues.
- **Paywalls** or messages begging for donations. If you want to buy me a coffee,
you can message me through GitHub discussions or mail me.
# Screenshots
<p align="middle">
<img src="screenshot-desktop.webp" height="250" alt="desktop screenshot" />
@ -146,7 +146,8 @@ the `slug_style` variable to `UID`. You can also set the length of those slug by
the `slug_length` variable. It defaults to 8, and a minimum of 4 is supported.
To enable public mode, set `public_mode` to `Enable`. With this, anyone will be able to add
links. Listing existing links or deleting links will need admin access using the password.
links. Listing existing links or deleting links will need admin access using the password. To
completely disable the frontend, set `disable_frontend` to `True`.
By default, the server sends no Cache-Control headers. You can set custom `cache_control_header`
to send your desired headers. It must be a comma separated list of valid
@ -154,6 +155,20 @@ to send your desired headers. It must be a comma separated list of valid
you can set it to `no-cache, private` to disable caching. It might help during testing if
served through a proxy.
## Deploying in your Kubernetes cluster with Helm
The helm values are very sparse to keep it simple. If you need more values to be variable, feel free to adjust.
The PVC allocates 100Mi and the PV is using a host path volume.
The helm chart assumes you have [cert manager](https://github.com/jetstack/cert-manager) deployed to have TLS certificates managed easily in your cluster. Feel free to remove the issuer and adjust the ingress if you're on AWS with EKS for example. To install cert-manager, I recommend using the ["kubectl apply" way](https://cert-manager.io/docs/installation/kubectl/) to install cert-manager.
To get started, `cp helm-chart/values.yaml helm-chart/my-values.yaml` and adjust `password`, `fqdn` and `letsencryptmail` in your new `my-values.yaml`, then just run
``` bash
cd helm-chart
helm upgrade --install chhoto-url . -n chhoto-url --create-namespace -f my-values.yaml
```
## Instructions for CLI usage
The application can be used from the terminal using something like `curl`. In all the examples
below, replace `http://localhost:4567` with where your instance of `chhoto-url` is accessible.

71
actix/Cargo.lock generated
View file

@ -31,7 +31,7 @@ dependencies = [
"actix-web",
"bitflags",
"bytes",
"derive_more 0.99.19",
"derive_more 0.99.20",
"futures-core",
"http-range",
"log",
@ -72,7 +72,7 @@ dependencies = [
"mime",
"percent-encoding",
"pin-project-lite",
"rand 0.9.0",
"rand 0.9.1",
"sha1",
"smallvec",
"tokio",
@ -351,9 +351,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.97"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
name = "autocfg"
@ -416,9 +416,9 @@ dependencies = [
[[package]]
name = "brotli-decompressor"
version = "4.0.2"
version = "4.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37"
checksum = "a334ef7c9e23abf0ce748e8cd309037da93e606ad52eb372e4ce327a0dcfbdfd"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
@ -441,9 +441,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.18"
version = "1.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c"
checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362"
dependencies = [
"jobserver",
"libc",
@ -458,7 +458,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chhoto-url"
version = "5.6.3"
version = "5.7.1"
dependencies = [
"actix-files",
"actix-session",
@ -466,7 +466,7 @@ dependencies = [
"env_logger",
"nanoid",
"passwords",
"rand 0.9.0",
"rand 0.9.1",
"regex",
"rusqlite",
"serde",
@ -562,9 +562,9 @@ dependencies = [
[[package]]
name = "derive_more"
version = "0.99.19"
version = "0.99.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f"
checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f"
dependencies = [
"convert_case",
"proc-macro2",
@ -760,9 +760,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.15"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
@ -1059,9 +1059,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jiff"
version = "0.2.6"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f33145a5cbea837164362c7bd596106eb7c5198f97d1ba6f6ebb3223952e488"
checksum = "5a064218214dc6a10fbae5ec5fa888d80c45d611aba169222fc272072bf7aef6"
dependencies = [
"jiff-static",
"log",
@ -1072,9 +1072,9 @@ dependencies = [
[[package]]
name = "jiff-static"
version = "0.2.6"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43ce13c40ec6956157a3635d97a1ee2df323b263f09ea14165131289cb0f5c19"
checksum = "199b7932d97e325aff3a7030e141eafe7f2c6268e1d1b24859b753a627f45254"
dependencies = [
"proc-macro2",
"quote",
@ -1099,15 +1099,15 @@ checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
[[package]]
name = "libc"
version = "0.2.171"
version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "libsqlite3-sys"
version = "0.32.0"
version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbb8270bb4060bd76c6e96f20c52d80620f1d82a3470885694e41e0f81ef6fe7"
checksum = "947e6816f7825b2b45027c2c32e7085da9934defa535de4a6a46b10a4d5257fa"
dependencies = [
"cc",
"pkg-config",
@ -1177,9 +1177,9 @@ dependencies = [
[[package]]
name = "miniz_oxide"
version = "0.8.7"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
dependencies = [
"adler2",
]
@ -1338,9 +1338,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "proc-macro2"
version = "1.0.94"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
@ -1373,13 +1373,12 @@ dependencies = [
[[package]]
name = "rand"
version = "0.9.0"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.3",
"zerocopy",
]
[[package]]
@ -1408,7 +1407,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.15",
"getrandom 0.2.16",
]
[[package]]
@ -1497,9 +1496,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rusqlite"
version = "0.34.0"
version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e34486da88d8e051c7c0e23c3f15fd806ea8546260aa2fec247e97242ec143"
checksum = "a22715a5d6deef63c637207afbe68d0c72c3f8d0022d7cf9714c442d6157606b"
dependencies = [
"bitflags",
"fallible-iterator",
@ -1616,9 +1615,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook-registry"
version = "1.4.2"
version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
dependencies = [
"libc",
]
@ -1742,9 +1741,9 @@ dependencies = [
[[package]]
name = "tokio-util"
version = "0.7.14"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034"
checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
dependencies = [
"bytes",
"futures-core",

View file

@ -3,7 +3,7 @@
[package]
name = "chhoto-url"
version = "5.6.3"
version = "5.7.1"
edition = "2021"
authors = ["Sayantan Santra <sayantan[dot]santra689[at]gmail[dot]com"]
license = "mit"
@ -29,7 +29,7 @@ categories = ["web-programming"]
[dependencies]
actix-web = "4.5.1"
actix-files = "0.6.5"
rusqlite = { version = "0.34.0", features = ["bundled"] }
rusqlite = { version = "0.35.0", features = ["bundled"] }
regex = "1.10.3"
rand = "0.9.0"
passwords = "3.1.16"

View file

@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2023 Sayantan Santra <sayantan.santra689@gmail.com>
// SPDX-License-Identifier: MIT
use rusqlite::Connection;
use rusqlite::{Connection, Error};
use serde::Serialize;
// Struct for encoding a DB row
@ -67,12 +67,11 @@ pub fn add_hit(shortlink: &str, db: &Connection) {
}
// Insert a new link
pub fn add_link(shortlink: String, longlink: String, db: &Connection) -> bool {
pub fn add_link(shortlink: String, longlink: String, db: &Connection) -> Result<usize, Error> {
db.execute(
"INSERT INTO urls (long_url, short_url, hits) VALUES (?1, ?2, ?3)",
(longlink, shortlink, 0),
)
.is_ok()
}
// Delete and existing link
@ -99,5 +98,12 @@ pub fn open_db(path: String) -> Connection {
)
.expect("Unable to initialize empty database.");
// Create index on short_url for faster lookups
db.execute(
"CREATE UNIQUE INDEX IF NOT EXISTS idx_short_url ON urls (short_url)",
[],
)
.expect("Unable to create index on short_url.");
db
}

View file

@ -40,6 +40,8 @@ async fn main() -> Result<()> {
.ok()
.filter(|s| !s.trim().is_empty());
let disable_frontend = env::var("disable_frontend").is_ok_and(|s| s.trim() == "True");
// If an API key is set, check the security
if let Ok(key) = env::var("api_key") {
if !auth::is_key_secure() {
@ -61,15 +63,9 @@ async fn main() -> Result<()> {
// Set the site_url without the quotes
env::set_var("site_url", url);
eprintln!("WARN: The site_url environment variable is encapsulated by quotes. Automatically adjusting to {}", url);
// Tell the user what URI the server will respond with
eprintln!("INFO: Public URI is: {url}:{port}.")
} else {
// No issues
eprintln!("INFO: Configured Site URL is: {site_url}.");
// Tell the user what URI the server will respond with
eprintln!("INFO: Public URI is: {site_url}:{port}.")
}
} else {
// Site URL is not configured
@ -82,7 +78,7 @@ async fn main() -> Result<()> {
// Actually start the server
HttpServer::new(move || {
App::new()
let mut app = App::new()
.wrap(middleware::Logger::default())
.wrap(middleware::Compress::default())
.wrap(
@ -108,9 +104,13 @@ async fn main() -> Result<()> {
.service(services::delete_link)
.service(services::login)
.service(services::logout)
.service(services::expand)
.service(Files::new("/", "./resources/").index_file("index.html"))
.default_service(actix_web::web::get().to(services::error404))
.service(services::expand);
if !disable_frontend {
app = app.service(Files::new("/", "./resources/").index_file("index.html"));
}
app.default_service(actix_web::web::get().to(services::error404))
})
// Hardcode the port the server listens to. Allows for more intuitive Docker Compose port management
.bind(("0.0.0.0", port))?

View file

@ -79,9 +79,9 @@ pub async fn add_link(
// Return http://
if port == 80 {
url = env::var("site_url")
.ok()
.filter(|s| !s.trim().is_empty())
.unwrap_or(String::from("http://localhost"));
.ok()
.filter(|s| !s.trim().is_empty())
.unwrap_or(String::from("http://localhost"));
}
// If the port is 443, remove the port from the returned URL (better for copying and pasting)
// Return https://

View file

@ -6,7 +6,7 @@ use actix_web::HttpRequest;
use nanoid::nanoid;
use rand::seq::IndexedRandom;
use regex::Regex;
use rusqlite::Connection;
use rusqlite::{ffi::SQLITE_CONSTRAINT_UNIQUE, Connection};
use serde::{Deserialize, Serialize};
use std::env;
@ -80,7 +80,11 @@ pub fn is_api_ok(http: HttpRequest) -> Response {
}
// Request the DB for searching an URL
pub fn get_longurl(shortlink: String, db: &Connection, needhits: bool) -> (Option<String>, Option<i64>) {
pub fn get_longurl(
shortlink: String,
db: &Connection,
needhits: bool,
) -> (Option<String>, Option<i64>) {
if validate_link(&shortlink) {
database::find_url(shortlink.as_str(), db, needhits)
} else {
@ -119,22 +123,30 @@ pub fn add_link(req: String, db: &Connection) -> (bool, String) {
len = 4;
}
if chunks.shortlink.is_empty() {
let shortlink_provided = if chunks.shortlink.is_empty() {
chunks.shortlink = gen_link(style, len);
}
if validate_link(chunks.shortlink.as_str())
&& get_longurl(chunks.shortlink.clone(), db, false).0.is_none()
{
(
database::add_link(chunks.shortlink.clone(), chunks.longlink, db),
chunks.shortlink,
)
false
} else {
(
false,
String::from("Short URL not valid or already in use!"),
)
true
};
if validate_link(chunks.shortlink.as_str()) {
match database::add_link(chunks.shortlink.clone(), chunks.longlink, db) {
Ok(_) => (true, chunks.shortlink),
Err(error) => {
if error.sqlite_error().map(|err| err.extended_code)
== Some(SQLITE_CONSTRAINT_UNIQUE)
&& shortlink_provided
{
(false, String::from("Short URL is already in use!"))
} else {
// This should be super rare
(false, String::from("Something went wrong!"))
}
}
}
} else {
(false, String::from("Short URL is not valid!"))
}
}

View file

@ -59,6 +59,9 @@ services:
# In case you want to provide public access to adding links (and not
# delete, or listing), change the following option to Enable.
# - public_mode=Disable
# In case you want to completely disable the frontend, change the following
# to True.
# - disable_frontend=False
# By default, the server sends no Cache-Control headers. You can supply a
# comma separated list of valid header as per RFC 7234 §5.2 to send those

24
helm-chart/Chart.yaml Normal file
View file

@ -0,0 +1,24 @@
apiVersion: v2
name: chhoto-url
description: A Helm chart for Kubernetes
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.16.0"

View file

@ -0,0 +1,23 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: chhoto-url
annotations:
cert-manager.io/issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
tls:
- hosts:
- {{ .Values.fqdn }}
secretName: my-tls
rules:
- host: {{ .Values.fqdn }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: chhoto-url
port:
number: 80

View file

@ -0,0 +1,18 @@
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: {{ .Values.letsencryptmail }}
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
ingressClassName: nginx

View file

@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: chhoto-pv
labels:
app: chhoto-url
spec:
capacity:
storage: 100Mi
accessModes:
- ReadWriteOnce
hostPath:
path: {{ .Values.persistence.hostPath.path }}

View file

@ -0,0 +1,10 @@
apiVersion: v1
kind: Secret
metadata:
name: secret
type: Opaque
data:
password: {{ .Values.password }}
{{- if .Values.api_key }}
api_key: {{ .Values.api_key }}
{{- end }}

View file

@ -0,0 +1,61 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: chhoto-url
spec:
replicas: 1
selector:
matchLabels:
app: chhoto-url
template:
metadata:
labels:
app: chhoto-url
spec:
containers:
- name: chhoto-url
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: 4567
env:
- name: password
valueFrom:
secretKeyRef:
name: secret
key: password
{{- if .Values.api_key }}
- name: api_key
valueFrom:
secretKeyRef:
name: secret
key: api_key
{{- end }}
- name: db_url
value: /db/urls.sqlite
- name: site_url
value: "{{ .Values.protocol }}://{{ .Values.fqdn }}"
- name: redirect_method
value: {{ .Values.redirect_method }}
- name: slug_style
value: {{ .Values.slug_style }}
- name: slug_length
value: "{{ .Values.slug_length }}"
- name: public_mode
value: {{ .Values.public_mode }}
- name: disable_frontend
value: {{ .Values.disable_frontend }}
{{- if .Values.cache_control_header }}
- name: cache_control_header
value: {{ .Values.cache_control_header }}
{{- end }}
volumeMounts:
- name: data
mountPath: /db
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 100Mi

View file

@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: chhoto-url
labels:
app: chhoto-url
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 4567
protocol: TCP
selector:
app: chhoto-url

28
helm-chart/values.yaml Normal file
View file

@ -0,0 +1,28 @@
# Default values for chhoto-url.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
image:
repository: sintan1729/chhoto-url
pullPolicy: IfNotPresent
tag: "5.4.6"
# please use a better password in your values and base64 encode it
password: cGFzc3dvcmQ=
# if used, needs to be base64 encoded as well
# api_key: U0VDVVJFX0FQSV9LRVk=
persistence:
hostPath:
path: /mnt/data/chhoto-data
redirect_method: PERMANENT
slug_style: Pair
slug_length: 8
public_mode: Disable
disable_frontend: False
# cache_control_header: "no-cache, private"
protocol: https
fqdn: your.short.link.url.com
letsencryptmail: your.mail@address.com