This commit is contained in:
v0id1st 2025-09-18 13:29:43 +02:00
commit 164a89ea3e
14 changed files with 673 additions and 0 deletions

9
README.md Normal file
View File

@ -0,0 +1,9 @@
# helpers - pliki pomocnicze dla projektu
Lista plików i katalogów:
- public_html/ --> template katalogu ze stroną dla użytkownika
- irc.conf --> domyślna konfiguracja weechat dla użytkownika
- add_user.sh --> skrypt służący do dodawania użytkownika
- del_user.sh --> skrypt służący do permanentnego usunięcia użytkownika
- cgenforce.sh --> skrypt uruchamiany z crona co minutę, podpina procesy wszystkich użytkowników pod cgroups w celu ustawienia limitów

89
add_user.sh Executable file
View File

@ -0,0 +1,89 @@
#!/bin/sh
# Usage: add_user.sh <login>
set -e
LOGIN="$1"
[ -z "$LOGIN" ] && { echo "Użycie: $0 <login>"; exit 1; }
# 1. Użytkownik i hasło
PASS="$(openssl rand -base64 12)"
adduser -D -s /bin/sh -h /home/$LOGIN -H "$LOGIN"
echo "$LOGIN:$PASS" | chpasswd
addgroup $LOGIN tildeusers
# 2. Dataset ZFS (quota 200MB)
zfs create -o mountpoint=/home/$LOGIN -o quota=200M tank/ROOT/homes/$LOGIN
chown $LOGIN:$LOGIN /home/$LOGIN
mkdir -p /home/$LOGIN/Maildir/Inbox/cur
mkdir -p /home/$LOGIN/Maildir/Inbox/new
mkdir -p /home/$LOGIN/Maildir/Inbox/tmp
mkdir -p /home/$LOGIN/Maildir/Sent/cur
mkdir -p /home/$LOGIN/Maildir/Sent/new
mkdir -p /home/$LOGIN/Maildir/Sent/tmp
mkdir -p /home/$LOGIN/Maildir/Drafts/cur
mkdir -p /home/$LOGIN/Maildir/Drafts/new
mkdir -p /home/$LOGIN/Maildir/Drafts/tmp
mkdir -p /home/$LOGIN/Maildir/Trash/cur
mkdir -p /home/$LOGIN/Maildir/Trash/new
mkdir -p /home/$LOGIN/Maildir/Trash/tmp
cp -r /root/helpers/public_html /home/$LOGIN/
sed -i "s/<<USER>>/$LOGIN/g" /home/$LOGIN/public_html/index.php
sed -i "s/<<USER>>/$LOGIN/g" /home/$LOGIN/public_html/parts/header.php
sed -i "s/<<USER>>/$LOGIN/g" /home/$LOGIN/public_html/blog/index.php
mkdir -p /home/$LOGIN/.config/weechat/
cp irc.conf /home/$LOGIN/.config/weechat
cat << EOF > /home/$LOGIN/.tmux.conf
set -g mouse on
setw -g mode-keys vi
bind -n F1 select-window -t 0
bind -n F2 select-window -t 1
bind -n F3 select-window -t 2
bind -n F12 detach
EOF
cat << EOF > /home/$LOGIN/.profile
if [ -z "$TMUX" ]; then
if ! tmux has-session -t main 2>/dev/null; then
tmux new-session -d -s main -n Mail 'neomutt'
tmux new-window -t main:1 -n IRC 'weechat'
tmux new-window -t main:2 -n Shell 'ash'
fi
# Uruchom motd tylko gdy user wchodzi do Shell okno 2
tmux send-keys -t main:2 '/usr/local/bin/tylda-motd.sh' C-m
tmux select-window -t main:0
exec tmux attach-session -t main
fi
EOF
chown -R $LOGIN:$LOGIN /home/$LOGIN/
# 3. Cgroup v2
CG_ROOT=/sys/fs/cgroup/users
mkdir -p "$CG_ROOT"
# upewnij się, że kontrolery włączone w parent „users”
echo "+cpu +memory" > "$CG_ROOT/cgroup.subtree_control" 2>/dev/null || true
USER_CG="$CG_ROOT/$LOGIN"
mkdir "$USER_CG"
sendmail -f void@tylda.org $LOGIN@tylda.org < welcome.txt
echo 524288000 > "$USER_CG/memory.max" # 500MB RAM
echo "50000 100000" > "$USER_CG/cpu.max" # 50% CPU (quota/period μs)
echo "===== NOWE KONTO ====="
echo "login : $LOGIN"
echo "hasło : $PASS"
echo "RAM : 500MB"
echo "CPU : 50%"

12
cgenforce.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh
USERS=$(ps | grep -v root | grep -v PID | awk '{print $2}' | uniq)
for i in 1 2 3 4 5 6 7 8 9 10 11 12; do
for user in $USERS; do
for pid in $(pgrep -u "$user"); do
echo "$pid" > "/sys/fs/cgroup/users/$user/cgroup.procs"
done
done
sleep 5
done

49
del_user.sh Executable file
View File

@ -0,0 +1,49 @@
#!/bin/sh
set -e
# === CONFIG ===
POOL="tank"
HOMES_DATASET="${POOL}/ROOT/homes"
MOUNTROOT="/home"
# === ARGUMENT ===
USERNAME="$1"
if [ -z "$USERNAME" ]; then
echo "Użycie: $0 <username>"
exit 1
fi
# === CONFIRM ===
echo "Na pewno chcesz usunąć użytkownika $USERNAME? [y/N]"
read -r CONFIRM
[ "$CONFIRM" != "y" ] && echo "Anulowano." && exit 1
echo "[i] Zabijam wszystkie procesy użytkownika $USERNAME..."
pkill -KILL -u "$USERNAME" 2>/dev/null || true
sleep 1 # Dajmy kernelowi chwilę na posprzątanie
# === REMOVE FROM CGROUPS ===
echo "[i] Odłączam procesy z cgroup (jeśli coś zostało)..."
rmdir "/sys/fs/cgroup/users/${USERNAME}"
# === UNMOUNT HOME DIR ===
ZFS_DATASET="${HOMES_DATASET}/${USERNAME}"
if mountpoint -q "${MOUNTROOT}/${USERNAME}"; then
echo "[i] Odmontowuję katalog ${MOUNTROOT}/${USERNAME}..."
umount "${MOUNTROOT}/${USERNAME}" || umount -l "${MOUNTROOT}/${USERNAME}" || true
fi
# === DESTROY ZFS DATASET ===
echo "[i] Usuwam dataset ZFS: $ZFS_DATASET"
zfs destroy "$ZFS_DATASET"
# === REMOVE USER FROM SYSTEM ===
echo "[i] Usuwam użytkownika systemowego..."
deluser --remove-home "$USERNAME" 2>/dev/null || true
rm -rf "${MOUNTROOT:?}/${USERNAME}"
echo "[+] Użytkownik $USERNAME został w pełni usunięty."

238
irc.conf Normal file
View File

@ -0,0 +1,238 @@
#
# weechat -- irc.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/weechat/quickstart/
#
config_version = 5
[look]
buffer_open_before_autojoin = on
buffer_open_before_join = off
buffer_switch_autojoin = on
buffer_switch_join = on
color_nicks_in_names = off
color_nicks_in_nicklist = off
color_nicks_in_server_messages = on
color_pv_nick_like_channel = on
ctcp_time_format = "%a, %d %b %Y %T %z"
display_account_message = on
display_away = local
display_ctcp_blocked = on
display_ctcp_reply = on
display_ctcp_unknown = on
display_extended_join = on
display_host_join = on
display_host_join_local = on
display_host_notice = on
display_host_quit = on
display_host_wallops = on
display_join_message = "329,332,333,366"
display_old_topic = on
display_pv_away_once = on
display_pv_back = on
display_pv_nick_change = on
display_pv_warning_address = off
highlight_channel = "$nick"
highlight_pv = "$nick"
highlight_server = "$nick"
highlight_tags_restrict = "irc_privmsg,irc_notice"
ignore_tag_messages = off
item_channel_modes_hide_args = "k"
item_display_server = buffer_plugin
item_nick_modes = on
item_nick_prefix = on
join_auto_add_chantype = off
list_buffer = on
list_buffer_format_export = "${name} (${users}): "${topic}""
list_buffer_scroll_horizontal = 10
list_buffer_sort = "~name2"
list_buffer_topic_strip_colors = on
msgbuffer_fallback = current
new_channel_position = none
new_list_position = none
new_pv_position = none
nick_completion_smart = speakers
nick_mode = prefix
nick_mode_empty = off
nicks_hide_password = "nickserv"
notice_as_pv = auto
notice_nicks_disable_notify = "chanserv,nickserv"
notice_welcome_redirect = on
notice_welcome_tags = ""
notify_tags_ison = "notify_message"
notify_tags_whois = "notify_message"
open_pv_buffer_echo_msg = on
part_closes_buffer = off
pv_buffer = independent
pv_tags = "notify_private"
raw_messages = 256
server_buffer = merge_with_core
smart_filter = on
smart_filter_account = on
smart_filter_chghost = on
smart_filter_delay = 5
smart_filter_join = on
smart_filter_join_unmask = 30
smart_filter_mode = "+"
smart_filter_nick = on
smart_filter_quit = on
smart_filter_setname = on
temporary_servers = off
topic_strip_colors = off
typing_status_nicks = off
typing_status_self = off
[color]
input_nick = lightcyan
item_lag_counting = default
item_lag_finished = yellow
item_nick_modes = default
item_tls_version_deprecated = yellow
item_tls_version_insecure = red
item_tls_version_ok = green
list_buffer_line_selected = white
list_buffer_line_selected_bg = 24
message_account = cyan
message_chghost = brown
message_join = green
message_kick = red
message_quit = red
message_setname = brown
mirc_remap = "1,-1:darkgray"
nick_prefixes = "y:lightred;q:lightred;a:lightcyan;o:lightgreen;h:lightmagenta;v:yellow;*:lightblue"
notice = green
reason_kick = default
reason_quit = 244
term_remap = "0,-1:darkgray"
topic_current = default
topic_new = 36
topic_old = 244
[network]
autoreconnect_delay_growing = 2
autoreconnect_delay_max = 600
ban_mask_default = "*!$ident@$host"
colors_receive = on
colors_send = on
lag_check = 60
lag_max = 1800
lag_min_show = 500
lag_reconnect = 300
lag_refresh_interval = 1
notify_check_ison = 1
notify_check_whois = 5
sasl_fail_unavailable = on
send_unknown_commands = off
whois_double_nick = off
[msgbuffer]
[ctcp]
clientinfo = "${clientinfo}"
source = "${download}"
time = "${time}"
version = "WeeChat ${version}"
[ignore]
[server_default]
addresses = ""
anti_flood = 2000
autoconnect = off
autojoin = ""
autojoin_delay = 0
autojoin_dynamic = off
autoreconnect = on
autoreconnect_delay = 10
autorejoin = off
autorejoin_delay = 30
away_check = 0
away_check_max_nicks = 25
capabilities = "*"
charset_message = message
command = ""
command_delay = 0
connection_timeout = 60
default_chantypes = "#&"
ipv6 = auto
local_hostname = ""
msg_kick = ""
msg_part = "WeeChat ${info:version}"
msg_quit = "WeeChat ${info:version}"
nicks = "${username},${username}2,${username}3,${username}4,${username}5"
nicks_alternate = on
notify = ""
password = ""
proxy = ""
realname = ""
registered_mode = "r"
sasl_fail = reconnect
sasl_key = ""
sasl_mechanism = plain
sasl_password = ""
sasl_timeout = 15
sasl_username = ""
split_msg_max_length = 512
tls = on
tls_cert = ""
tls_dhkey_size = 2048
tls_fingerprint = ""
tls_password = ""
tls_priorities = "NORMAL"
tls_verify = on
usermode = ""
username = "${username}"
[server]
tylda.addresses = "irc.tylda.org"
tylda.proxy
tylda.ipv6
tylda.tls = off
tylda.tls_cert
tylda.tls_password
tylda.tls_priorities
tylda.tls_dhkey_size
tylda.tls_fingerprint
tylda.tls_verify
tylda.password
tylda.capabilities
tylda.sasl_mechanism
tylda.sasl_username
tylda.sasl_password
tylda.sasl_key
tylda.sasl_timeout
tylda.sasl_fail
tylda.autoconnect = on
tylda.autoreconnect
tylda.autoreconnect_delay
tylda.nicks
tylda.nicks_alternate
tylda.username
tylda.realname
tylda.local_hostname
tylda.usermode
tylda.command_delay
tylda.command
tylda.autojoin_delay
tylda.autojoin
tylda.autojoin_dynamic
tylda.autorejoin
tylda.autorejoin_delay
tylda.connection_timeout
tylda.anti_flood
tylda.away_check
tylda.away_check_max_nicks
tylda.msg_kick
tylda.msg_part
tylda.msg_quit
tylda.notify
tylda.split_msg_max_length
tylda.charset_message
tylda.default_chantypes
tylda.registered_mode

View File

@ -0,0 +1,30 @@
<?php
ini_set("display_errors", "On");
error_reporting(E_ALL);
include '../parts/header.php';
?>
<div id="top-bar">
<h1>> Blog</h1>
</div>
<article id="content">
<div class="post">Poniżej znajdziesz listę wszystkich postów na blogu ~<<USER>></div>
<?php
$posts_dir = 'posts/';
$posts = array_diff(scandir($posts_dir), array('..', '.'));
foreach ($posts as $post) {
$f = fopen("posts/$post", "r");
$line = fgets($f);
fclose($f);
$data = substr(substr($line, 4), 0, -4);
$post_data = explode(";%%%;", $data);
$title = $post_data[0];
$date = $post_data[1];
echo "<div class=\"post\"><i class=\"post_date\">$date</i> - <a href=\"posts/$post\" class=\"link\">$title</a></div>";
}
?>
</article>
<?php
include '../parts/footer.php';
?>

16
public_html/blog/newpost Normal file
View File

@ -0,0 +1,16 @@
#title:Tytuł posta
Tutaj zaczyna się treść posta, dozwolony markdown
# Nagłówek
## Nagłówek 2
![alt](image.png)
> to
> jest
> cytat
```
a tu kod
```

View File

@ -0,0 +1,11 @@
<!-- Witaj świecie!;%%%;2025-07-29 17:33:01 -->
<?php include '../../parts/header.php'; ?>
<div id="top-bar">
<h1>> Witaj świecie!</h1>
</div>
<i class="post_date">2025-07-29 17:33:01</i>
<article id="content">
<p>To jest pierwszy post na twojej stronie. Możesz go usunąć usuwając plik witaj-swiecie.php :)</p>
</article>
<?php include '../../parts/footer.php'; ?>

57
public_html/index.php Normal file
View File

@ -0,0 +1,57 @@
<?php
include 'parts/header.php';
?>
<div id="top-bar">
<h1>> Strona Główna</h1>
</div>
<article id="content">
<pre>
__ __ _ _
\ \ / /__| | ___ ___ _ __ ___ ___ | |_ ___
\ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \ | __/ _ \
\ V V / __/ | (_| (_) | | | | | | __/ | || (_) |
\_/\_/ \___|_|\___\___/|_| |_| |_|\___| \__\___/
</pre>
<h1>Witaj na swojej stronie, <code><<USER>></code>!</h1>
<p>
To Twoja osobista przestrzeń w <strong>systemie Tylda</strong> tu możesz pisać bloga, eksperymentować z HTML, PHP, Ash, Perl, Python… albo po prostu zostawić wiadomość dla świata.
</p>
<p>
Twój katalog to <code>/home/<<USER>>/</code><br>
Twoja strona jest dostępna w katalogu: <code>/home/<<USER>>/public_html/</code>
</p>
<hr>
<h2>Co możesz teraz zrobić?</h2>
<ul>
<li>Edytuj ten plik, by zacząć tworzyć swoją stronę</li>
<li>Dodaj wpis na bloga: <code>komenda <i>blog</i></code></li>
<li>Dołącz do czatu IRC na <code>#ogolny</code> (WeeChat)</li>
<li>Sprawdź skrzynkę: <code>neomutt</code></li>
<li>Dodaj swój styl: stwórz <code>style.css</code></li>
</ul>
<hr>
<p>
Chcesz więcej inspiracji? Zajrzyj do innych użytkowników: <a class="link" href="/users.php">Lista użytkowników</a><br>
Albo odwiedź <a class="link" href="https://tildeverse.org">tildeverse.org</a>, by zobaczyć inne społeczności.
</p>
<p>
Niech Twój katalog rośnie razem z Tobą. Baw się dobrze i nie bój się próbować!
</p>
<pre>
~ v0id1st
</pre>
</article>
<?php
include 'parts/footer.php';
?>

View File

@ -0,0 +1,4 @@
</div>
</body>
</html>

View File

@ -0,0 +1,21 @@
<?php
$req = $_SERVER['REQUEST_URI'];
?>
<html lang="pl">
<head>
<link rel="stylesheet" type="text/css" href="/~<<USER>>/style.css">
<?php
if (str_contains($req, "/blog/")) {
echo '<title>~<<USER>> Blog | tylda.org</title>';
} else {
echo '<title>~<<USER>> | tylda.org</title>';
}
?>
</head>
<body>
<div class="main-content">
<header id="menu">
<a href="/~<<USER>>/">~<<USER>></a>
<a <?php if ($req == "/~<<USER>>/" || $req == "~/<<USER>>/index.php") { echo 'class="active"'; } ?>href="/~<<USER>>/">strona główna</a>
<a <?php if (str_starts_with($req, "/~<<USER>>/blog/")) { echo 'class="active"'; } ?>href="/~<<USER>>/blog/">blog</a>
</header>

View File

@ -0,0 +1,8 @@
<div id="top-bar">
<h1>> <<TITLE>></h1>
</div>
<i class="post_date"><<DATE>></i>
<article id="content">
<<CONTENT>>
</article>

125
public_html/style.css Normal file
View File

@ -0,0 +1,125 @@
@media only screen and (max-width: 850px) {
header#menu {
flex-direction: column !important;
}
}
:root {
--main: #dd9a1a;
--bg: #111;
--link: #ffdb96;
--link-hover: #dd9a1a;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: var(--bg);
color: var(--main);
font-family: "Helvetica", "Arial", sans-serif;
}
div.main-content {
display: flex;
flex-direction: column;
width: 60%;
margin: 0 auto;
padding: 1rem;
}
header#menu {
display: flex;
flex-direction: row;
height: 3rem;
border-width: 5px;
border-color: var(--main);
border-style: double;
border-radius: 5px;
margin-bottom: 2rem;
align-items: center;
}
header#menu a {
padding: 7px;
color: var(--main);
text-decoration: none;
text-transform: uppercase;
padding-inline: 30px;
font-weight: bold;
}
header#menu a.active {
background: var(--main);
color: var(--bg);
}
header#menu a:hover {
background: var(--main);
color: var(--bg);
}
div#top-bar {
font-family: 'Courier New';
}
article#content {
display: flex;
flex-direction: column;
border-width: 5px;
border-color: var(--main);
border-style: double;
border-radius: 5px;
margin-top: 2rem;
padding: 1rem;
gap: 8px;
padding-block: 2rem;
}
footer#footer {
margin-top: 3rem;
display: flex;
flex-direction: row;
gap: 1rem;
justify-content: center;
}
.link {
color: var(--link);
text-decoration: none;
}
.link:hover {
color: var(--link-hover);
}
footer#footer > *:not(:last-child)::after {
content: " ~ ";
margin-left: 0.7rem;
color: var(--main);
}
pre.ascii {
margin-bottom: 2rem;
font-size: 15px;
}
.user_home {
display: grid;
grid-template-columns: 100px 30px 100px 100px 40px 120px 15px;
font-family: monospace;
white-space: pre;
}
ol, ul {
margin-left: 2rem;
}
.post {
display: flex;
gap: 1rem;
}

4
welcome.txt Normal file
View File

@ -0,0 +1,4 @@
Subject: Witaj na tylda.org!
From: v0id1st@tylda.org
Siemano :D