Linux Servers Set Up & Management

  • 2 members
  • 2 followers
  • 3349 views
  • Pay & Join
  • More
Added a class   to  , Linux Servers Set Up & Management

API?leak remediation & hardening playbook

This is tuned for your stack (Debian 12 in LXC with Docker, Apache2 reverse proxy to Uvicorn/Streamlit & Node/n8n). The leak source was /var/www/html/flast/.env.

0) Immediate containment (do these first)

# 0.1 Rotate/revoke all keys found in the leaked .env (provider dashboards)
#     Then update the container with the new values after step 2 below.

# 0.2 Make the current file unreadable by anyone except owner (as a stopgap)
chmod 600 /var/www/html/flast/.env
chown root:root /var/www/html/flast/.env   # temporary; see step 2 for final layout

# 0.3 Block public access to dotfiles at the web tier (Apache)
cat >/etc/apache2/conf-available/deny-dotfiles.conf <<'EOF'
# Deny all access to dotfiles like .env, .git, .ht*, etc.
<FilesMatch "^\.">
  Require all denied
</FilesMatch>
Options -Indexes
EOF

a2enconf deny-dotfiles
systemctl reload apache2

# 0.4 Quick sanity: these must NOT return the file contents
curl -sI http://127.0.0.1/.env | head -n1   # expect 403/404
curl -skI https://127.0.0.1/.env | head -n1 # if SSL locally

1) Forensics: did anyone fetch .env?

# Access attempts to .env (status code focus)
zgrep -h "\.env" /var/log/apache2/access.log* 2>/dev/null | \
  awk '{print $(NF-1)}' | sort | uniq -c | sort -nr

# Top IPs that tried
zgrep -h "\.env" /var/log/apache2/access.log* 2>/dev/null | \
  awk '{print $1}' | sort | uniq -c | sort -nr | head

# Full lines for any 200/206 responses (bad)
zgrep -h "\.env" /var/log/apache2/access.log* 2>/dev/null | \
  awk '$9 ~ /^(200|206)$/ {print}' | tail -n +1

# If behind reverse proxy / other vhosts, also scan their logs

If you see 200/206, assume the contents were retrieved. Rotate all affected secrets and audit for misuse.

2) Move secrets out of the webroot (recommended layout)

Put app secrets in a root?only directory outside the document root, and load via systemd or Docker secrets.

2A) If running services via systemd on the CT

# Create a dedicated dir for secrets
install -d -m 0750 -o root -g root /etc/flast
install -m 0640 -o root -g root /etc/flast/flast.env
# Paste NEW rotated values into /etc/flast/flast.env in KEY=VALUE lines

# Point services to this EnvironmentFile
mkdir -p /etc/systemd/system/flast.server.service.d /etc/systemd/system/flast.client.service.d
cat >/etc/systemd/system/flast.server.service.d/env.conf <<'EOF'
[Service]
EnvironmentFile=/etc/flast/flast.env
EOF
cat >/etc/systemd/system/flast.client.service.d/env.conf <<'EOF'
[Service]
EnvironmentFile=/etc/flast/flast.env
EOF

# Reload & restart
systemctl daemon-reload
systemctl restart flast.server.service flast.client.service

# Verify the new env is in effect (will print service env, redact if needed)
systemctl show flast.server.service | grep ^Environment=

2B) If using Docker for the app

Prefer Docker secrets or a bind?mounted file owned by root:

# docker-compose.yml (example fragment)
services:
  app:
    image: your/app
    env_file: []            # avoid plaintext here for sensitive keys
    secrets:
      - flast_env
secrets:
  flast_env:
    file: /etc/flast/flast.env   # managed on the host CT as above

Then docker compose up -d to apply.

Remove /var/www/html/flast/.env after services run cleanly from /etc/flast/flast.env.
shred -u /var/www/html/flast/.env   # permanently delete old copy

3) Extra web hardening

Apache: ensure no directory indexes or source exposure.

# In your site .conf (e.g., /etc/apache2/sites-available/*.conf)
<Directory /var/www/html>
  Options -Indexes -Includes -ExecCGI
  AllowOverride None
  Require all granted
</Directory>

# (already added) protect dotfiles in conf-available/deny-dotfiles.conf

Reload:

apachectl -t && systemctl reload apache2

If you ever switch to Nginx:

location ~ /\. { deny all; }
autoindex off;

4) Process/env hygiene

After rotating keys, restart any process that might still have the old key in its environment or memory.

systemctl restart flast.server.service flast.client.service apache2 docker

# Spot-check that no process still carries sensitive env
for pid in $(pgrep -u flast -x python3 node); do
  sudo tr '\0' '\n' </proc/$pid/environ | egrep -i 'KEY|TOKEN|SECRET' || true
done

5) Backups: avoid bundling plaintext secrets

Your vzdump LXC backups currently include the webroot. Options:

  • Best: keep secrets in /etc/flast/flast.env and re-provision on restore (Ansible, script, or manual). No secrets in backups.
  • If you must exclude a path: add to your job or global config:
# One-off
vzdump 445 --exclude-path /var/www/html/flast/.env ...

# Or in /etc/vzdump.conf
# exclude-path: /var/www/html/flast/.env
Note: Excluding secrets means restores need a post-step to re-create /etc/flast/flast.env.

If/when you move to Proxmox Backup Server, use client?side encryption and keep secrets off the image.

6) File system & repo checks

# Search for other env files near the webroot
find /var/www -type f \( -name '.env' -o -name '*.env' \) -maxdepth 4

# If the project uses git, ensure .env is ignored and not committed
grep -nE '^\s*\.env(\b|$)' /var/www/html/flast/.gitignore || echo 'Missing .env in .gitignore'

git -C /var/www/html/flast log -p --follow -- .env 2>/dev/null | tail -n +1 || echo 'No .env in git history (good)'

If .env ever hit git history, purge with git filter-repo (or git filter-branch) and rotate keys again.

7) Optional: fail2ban rule to block .env scanners

# /etc/fail2ban/filter.d/apache-no-dotenv.conf
[Definition]
failregex = <HOST> - - \[.*\] "(GET|POST) /.*\.env.* HTTP/.*" 4(?:0[34]|5\d)
ignoreregex =

# /etc/fail2ban/jail.d/apache-no-dotenv.local
[apache-no-dotenv]
enabled = true
port    = http,https
filter  = apache-no-dotenv
logpath = /var/log/apache2/access.log
maxretry = 1
findtime = 3600
bantime  = 86400
systemctl restart fail2ban
fail2ban-client status apache-no-dotenv

8) LXC hardening notes for this CT

You need nesting=1 for Docker. Still, keep it tight:

  • Make sure unprivileged containers for future workloads when possible. This CT is privileged; restrict mounts and capabilities.
  • Proxmox firewall: allow only required inbound ports (80/443, 30000/31000 if truly public, 6333/5678 if needed). Block everything else.
  • Within CT, restrict Apache to bind only on expected interfaces.
  • Consider link_down=1 during incident response to pause egress.

9) Quick verification checklist

  • curl -I / .env returns 403/404.
  • /var/www/html/flast/.env does not exist (moved & shredded) or is 600 and outside DocumentRoot.
  • Services load env from /etc/flast/flast.env and run OK.
  • No process exposes secrets in /proc/*/environ.
  • Apache/Nginx denies dotfiles; Options -Indexes set.
  • Backups do not include plaintext secrets.
  • All leaked keys have been rotated.

___________ Refined _____________if 200 OK in Test

What your test shows

So yes, the .env is currently accessible over HTTPS from the container. We’ll fix it without changing ownership to root.

0) Inspect: which vhost & where is DocumentRoot

apachectl -S | sed -n '1,120p'
# Find the active HTTPS vhost and its DocumentRoot
grep -R "^\s*DocumentRoot\b\|^\s*Alias\b" /etc/apache2/sites-enabled/ -n

# Confirm where the file lives and its perms
stat -c '%a %U %G %n' /var/www/html/flast/.env
  • If your HTTPS vhost DocumentRoot is /var/www/html/flast, then /.env maps to /var/www/html/flast/.env.

1) Immediate mitigation (no owner change)

Keep owner as flast:flast, but remove world-read and group-read by webserver users.

# Keep owner as-is (flast). Just tighten mode so Apache (www-data) cannot read it.
chmod 0640 /var/www/html/flast/.env
# If group is not flast, set it to flast so only user+group flast can read:
chgrp flast /var/www/html/flast/.env

# Re-test locally
curl -sI http://127.0.0.1/.env | head -n1    # expect 404 as before
curl -skI https://127.0.0.1/.env | head -n1   # expect **403 Forbidden** now (Apache can't read)
If you still get 200 OK after chmod 0640, your app or a reverse proxy is serving it via a route. Proceed to step 2.

2) Web-server deny rule for dotfiles (keeps apps happy)

Create a small Apache conf that blocks any dotfile (including .env) but allows /.well-known/ for ACME.

cat >/etc/apache2/conf-available/hide-dotfiles.conf <<'EOF'
# Deny requests for any dotfile (.env, .git, .ht*, etc.)
# but keep ACME HTTP-01 working (.well-known).
<Directory "/var/www/html">
    <FilesMatch "^\.(?!well-known/)">
        Require all denied
    </FilesMatch>
</Directory>
EOF

# Adjust the Directory path above if your HTTPS vhost has a different DocumentRoot.

# Enable and reload
a2enconf hide-dotfiles
apachectl configtest && systemctl reload apache2

# Verify
curl -skI https://127.0.0.1/.env | head -n1   # expect 403 or 404
If you use per-site vhost files, you can put the <Directory> block directly into that site’s :443 vhost instead of a global conf.

3) (Recommended) Move secrets out of web root (still no owner change)

Keeping secrets in a served tree is risky even when denied. Prefer a location outside the DocumentRoot (owner/group flast:flast, mode 0600 or 0640).

install -o flast -g flast -m 0600 /var/www/html/flast/.env /etc/flast/flast.env
# Leave a placeholder so nothing breaks, but empty it to avoid accidental reads
: > /var/www/html/flast/.env && chmod 000 /var/www/html/flast/.env

Wire your app to the new path in one of these ways:

A) python-dotenv inside your app entrypoint

from dotenv import load_dotenv
load_dotenv('/etc/flast/flast.env')

B) systemd unit for uvicorn/streamlit

# /etc/systemd/system/flast.server.service (example)
[Service]
User=flast
Group=flast
EnvironmentFile=/etc/flast/flast.env
# ExecStart=... (your current command)

# Then:
systemctl daemon-reload
systemctl restart flast.server

C) Docker (if the app runs in a container)

# Add to your docker run / compose:
--env-file /etc/flast/flast.env

4) Check if it was ever fetched (forensics)

# Apache access logs (both current and rotated)
awk '$7 ~ /^\/.env$/ {print}' /var/log/apache2/access.log*
# If behind reverse proxy/stunnel, also search their logs
journalctl -u stunnel --since '7 days ago' | grep -F ' /.env '

If you find hits, rotate/replace the API key that was exposed.

5) Quick verification checklist

  • chmod 0640 (or 0600) on the real secrets file, owner/group flast:flast.
  • curl -skI https://127.0.0.1/.env returns 403/404, not 200.
  • Apache conf added & reloaded (or vhost updated) with the dotfile deny.
  • (Recommended) App loads secrets from /etc/flast/flast.env (outside webroot).
  • Keys rotated if any access was observed in logs.
Added a class   to  , Linux Servers Set Up & Management

N8N QDRANT POSTGRES DOCKER OLLAMA

Go here to check the current release

https://github.com/n8n-io/self-hosted-ai-starter-kit

Cloning the Repository

git clone https://github.com/n8n-io/self-hosted-ai-starter-kit.git
cd self-hosted-ai-starter-kit

Get Encryption Key and JWT Secret

openssl rand -hex 32

openssl rand -hex 64 

Edit .env and insert the keys as well as the database credentials.

nano .env

Edit docker compose.yaml

environment:

   - N8N_HOST=n8n.hexucation.org

   - N8N_PORT=5678

   - WEBHOOK_URL=https://n8n.hexucation.org

ports:-"5434:5432"

To Start :

docker compose --profile cpu up
Added a class   to  , Linux Servers Set Up & Management

# Proxmox Container Setup with Nginx Reverse Proxy, Apache, and Stunnel

This provides a comprehensive guide to configure a Proxmox environment where a container running Apache (with stunnel for SSL on a custom port) is served by a Proxmox-hosted Nginx reverse proxy and iptables NAT rules.

---

## Overview

- **Proxmox Host:**

 - Public IP: `74.91.24.10` on `vmbr0`.

 - Runs Nginx as a reverse proxy for HTTP (port 80).

 - Uses iptables NAT rules to forward traffic on custom ports (e.g. 31001) to containers.

- **Private Network (vmbr1):**

 - A dedicated internal bridge with IP `192.168.100.1/24`.

 - Containers attached to this bridge use private IPs.

- **Container:**

 - Assigned IP: `192.168.100.10/24` (with gateway `192.168.100.1`).

 - Runs Apache to serve web content.

 - Runs stunnel to handle SSL on port `31001`, forwarding to a local service (e.g., port `30000`).

 - Uses Certbot (via Apache or stunnel) for Let's Encrypt certificates.

---

## 1. Create a Private Bridge on Proxmox

1. **Log into Proxmox Web UI** and navigate to **Datacenter > Node > System > Network**.

2. **Add a New Linux Bridge (`vmbr1`):**

  - **Name:** `vmbr1`

  - **IPv4/CIDR:** `192.168.100.1/24`

  - **Bridge Ports:** Leave empty (not attached to a physical NIC).

  - **Autostart:** Enabled

---

## 2. Configure the Container

In the container's network configuration (accessible via the Proxmox web interface or by editing `/etc/pve/lxc/<CTID>.conf`):

- **Network Interface (`net0`):**

 ```ini

 net0: name=eth0,bridge=vmbr1,firewall=1,gw=192.168.100.1,ip=192.168.100.10/24,hwaddr=XX:XX:XX:XX:XX:XX

Set Up NAT on the Proxmox Host

3.1 Enable IP Forwarding

Edit /etc/sysctl.conf and add or ensure:

ini

Copy
net.ipv4.ip_forward=1 

Then apply the changes:

bash

Copy
sudo sysctl -p 

3.2 Add iptables NAT Rules

Forward external traffic on port 31001 to the container:

bash

Copy
sudo iptables -t nat -A PREROUTING -p tcp -i vmbr0 --dport 31001 -j DNAT --to-destination 192.168.100.10:31001 sudo iptables -A FORWARD -p tcp -d 192.168.100.10 --dport 31001 -j ACCEPT 

3.3 Persist the iptables Rules

Install the iptables-persistent package:

bash

Copy
sudo apt-get update sudo apt-get install iptables-persistent 

During installation, choose “Yes” to save current IPv4/IPv6 rules.

Or manually save the rules:

bash

Copy
sudo netfilter-persistent save 

Rules will be stored in /etc/iptables/rules.v4 (IPv4) and /etc/iptables/rules.v6 (IPv6) and loaded on boot.

4. Configure Nginx Reverse Proxy on the Proxmox Host

Create a server block file for your domain:

  1. Create the File:
bash

Copy
sudo nano /etc/nginx/sites-available/marina.flast.com.au 
  1. Insert the Following Configuration:
nginx

Copy
server { listen 80; server_name marina.flast.com.au; # Increase timeouts for larger responses (optional) proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; location / { proxy_pass http://192.168.100.10; 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; } } 
  1. Enable the Site:
bash

Copy
sudo ln -s /etc/nginx/sites-available/marina.flast.com.au /etc/nginx/sites-enabled/ sudo nginx -t && sudo systemctl reload nginx 

Note: Traffic on port 31001 is handled by the NAT rules. No extra Nginx block is needed for that port unless you prefer central SSL termination on the host.

5. Configure Stunnel in the Container

In the container, edit your stunnel configuration file (e.g., /etc/stunnel/streamlit.conf):

ini

Copy
[Engine-Flast] accept = 0.0.0.0:31001 connect = 30000 # Ensure this matches the destination service port in Apache or your application cert = /etc/letsencrypt/live/marina.flast.com.au/fullchain.pem key = /etc/letsencrypt/live/marina.flast.com.au/privkey.pem 

Restart stunnel to apply changes:

bash

Copy
sudo systemctl restart stunnel 

Verify stunnel is listening:

bash

Copy
sudo netstat -tulpn | grep 31001 

6. Configure Apache in the Container

Your Apache SSL configuration (e.g., /etc/apache2/sites-available/000-default-le-ssl.conf) should include your certificate paths and proxy settings. For example:

apache

Copy
<IfModule mod_ssl.c> <VirtualHost *:443> ServerAdmin webmaster@localhost DocumentRoot /var/www/html/flast ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined # Proxy settings for API and Engine ProxyPass /api/generate_answers/ http://localhost:31000/generate_answers/ ProxyPassReverse /api/generate_answers/ http://localhost:31000/generate_answers/ ProxyPass /engine http://localhost:31000 ProxyPassReverse /engine http://localhost:31000 ServerName marina.flast.com.au Include /etc/letsencrypt/options-ssl-apache.conf SSLCertificateFile /etc/letsencrypt/live/marina.flast.com.au/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/marina.flast.com.au/privkey.pem </VirtualHost> </IfModule> 

Ensure the ports in your Apache config match the stunnel “connect” port (adjust 30000 vs. 31000 as necessary).

7. Testing and Verification

bash

Copy
curl -I https://localhost:31001 
  • Verify Apache logs for proxied requests.
  • Verify NAT Rules on Proxmox:
bash

Copy
sudo iptables -t nat -L -n -v 

8. Certificates with Certbot (Optional)

If needed, use Certbot to obtain or renew certificates. For Apache in the container:

bash

Copy
sudo certbot --apache -d marina.flast.com.au 

Or, if you prefer to handle certificates on the Proxmox host using Nginx:

bash

Copy
sudo certbot --nginx -d marina.flast.com.au 

Ensure your domain's DNS points to 74.91.24.10.

Conclusion

This setup ensures:

  • A dedicated private network (vmbr1) for container communication.
  • The container uses a static private IP (192.168.100.10) with 192.168.100.1 as the gateway.
  • NAT rules on the Proxmox host forward custom port traffic (e.g., 31001) to the container.
  • Nginx on the Proxmox host handles domain-based routing for HTTP traffic.
  • The container runs stunnel to manage SSL connections on port 31001 and Apache to serve content.
  • iptables rules are made persistent using the iptables-persistent package.

Adjust any configuration parameters to match your specific environment and requirements. Happy hosting!

yaml

Copy
Added a class   to  , Linux Servers Set Up & Management

A comprehensive installation and configuration manual that consolidates all the insights from our previous discussions. It walks you through installing, configuring, and managing a Postfix + Dovecot + MySQL + Roundcube mail server on a typical Ubuntu/Debian system. It includes SSL/TLS, SMTP AUTH, MySQL-based virtual users, and Roundcube webmail.

Installation Manual:

Postfix + Dovecot + MySQL + Roundcube Setup

Table of Contents

  1. Introduction
  2. Prerequisites & Basic System Setup
  3. Install Required Packages
  4. Configure MySQL for Virtual Domains & Users
  5. Configure Postfix
  6. Configure Dovecot
  7. Configure Roundcube
  8. SSL Certificates with Let’s Encrypt (Optional)
  9. Testing the Setup
  10. Managing Users
  11. Enabling Sent Folders & Basic Roundcube Customization
  12. Troubleshooting Tips

1. Introduction

This guide describes how to build a mail server that uses:

  • Postfix as the SMTP server (handles sending and receiving).
  • Dovecot as the IMAP/POP3 server for mail storage and authentication.
  • MySQL for storing virtual domain and mailbox information.
  • Roundcube as a webmail client.

When completed, you’ll have:

  • Encrypted (TLS) IMAP on port 993 and SMTP on port 587 (for sending).
  • MySQL-based user accounts (no need for system users).
  • A Roundcube webmail interface for sending and receiving mail.

2. Prerequisites & Basic System Setup

  1. Ubuntu or Debian server with root or sudo privileges.
  2. A FQDN (Fully Qualified Domain Name) for your mail server, e.g. mail.example.com.
  3. DNS records pointing mail.example.com to your server’s IP.
  4. Open ports on your firewall:
  • 25 (SMTP inbound), 587 (SMTP submission), 993 (IMAP), 995 or 110 (POP3, optional), 80/443 for Let’s Encrypt if using web-based ACME.
  1. SSL certificate (Let’s Encrypt or other). This guide shows optional Let’s Encrypt steps in Section 8.

Make sure your server’s hostname is set correctly:

sudo hostnamectl set-hostname mail.example.com

3. Install Required Packages

Update your system and install essential mail-related packages:

sudo apt-get update
sudo apt-get install postfix postfix-mysql dovecot-core dovecot-imapd dovecot-pop3d \
  dovecot-mysql mysql-server libsasl2-2 libsasl2-modules pwgen \
  apache2 php php-mysql # (for Roundcube via Apache/PHP)
Note: If you prefer Nginx or another web server, install that instead of Apache.
During Postfix installation, it may ask “General type of mail configuration”—choose “Internet Site” or something minimal, since we’ll override it with our custom configs.

4. Configure MySQL for Virtual Domains & Users

4.1 Create Database & User

If not done already:

sudo mysql -u root -p

Then:

CREATE DATABASE mailserver;
CREATE USER 'mail_admin'@'localhost' IDENTIFIED BY 'SomeStrongPassword';
GRANT ALL PRIVILEGES ON mailserver.* TO 'mail_admin'@'localhost';
FLUSH PRIVILEGES;
EXIT;

4.2 Create Tables

Inside mailserver, we usually have:

  • A domain table for each domain (e.g. example.com).
  • A mailbox table for each user/mailbox.
  • An alias (or forwardings) table for any aliases.

For example:

USE mailserver;

CREATE TABLE domain (
  domain VARCHAR(50) NOT NULL,
  PRIMARY KEY (domain)
);

CREATE TABLE mailbox (
  username VARCHAR(100) NOT NULL,
  password VARCHAR(255) NOT NULL,
  name VARCHAR(100) NOT NULL,
  maildir VARCHAR(255) NOT NULL,
  quota INT(10) NOT NULL DEFAULT 0,
  local_part VARCHAR(64) NOT NULL,
  domain VARCHAR(50) NOT NULL,
  created DATETIME NOT NULL,
  modified DATETIME NOT NULL,
  active TINYINT(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (username)
);

CREATE TABLE alias (
  address VARCHAR(100) NOT NULL,
  goto TEXT NOT NULL,
  domain VARCHAR(50) NOT NULL,
  created DATETIME NOT NULL,
  modified DATETIME NOT NULL,
  active TINYINT(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (address)
);
Adjust sizes/columns as needed.

4.3 Insert Your Domain

INSERT INTO domain (domain) VALUES ('example.com');

4.4 MySQL Queries for Postfix & Dovecot

We’ll reference these .cf files in Postfix’s config. They typically contain lines like:

/etc/postfix/mysql-virtual-mailbox-domains.cf:

user = mail_admin
password = SomeStrongPassword
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM domain WHERE domain='%s'

/etc/postfix/mysql-virtual-mailbox-maps.cf:

user = mail_admin
password = SomeStrongPassword
hosts = 127.0.0.1
dbname = mailserver
query = SELECT maildir FROM mailbox WHERE username='%s' AND active=1

/etc/postfix/mysql-virtual-alias-maps.cf:

user = mail_admin
password = SomeStrongPassword
hosts = 127.0.0.1
dbname = mailserver
query = SELECT goto FROM alias WHERE address='%s' AND active=1
Make sure each file is owned by root:root and has 0600 or similarly restrictive permissions.

5. Configure Postfix

5.1 Main Configuration (/etc/postfix/main.cf)

Key directives (some lines might already exist):

myhostname = mail.example.com
mydomain = example.com
myorigin = /etc/mailname
mydestination = $myhostname, localhost.$mydomain, localhost
relayhost =

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
append_dot_mydomain = no
biff = no
inet_interfaces = all
inet_protocols = all

# Virtual domains
virtual_mailbox_base = /var/vmail
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_transport = lmtp:unix:private/dovecot-lmtp

virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf

# TLS
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1

# Authentication
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname

smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
smtpd_recipient_restrictions = permit_mynetworks,permit_sasl_authenticated,reject_unauth_destination
Adjust to match your paths and Let’s Encrypt cert. If you’re not using Let’s Encrypt, point to your existing SSL cert/key.

5.2 Master Configuration (/etc/postfix/master.cf)

Make sure submission (port 587) is enabled:

submission inet n       -       y       -       -       smtpd
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_tls_security_level=encrypt
  -o smtpd_tls_wrappermode=no
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject_unauth_destination
  -o smtpd_sasl_security_options=noanonymous
  -o smtpd_sasl_local_domain=$myhostname
  -o smtpd_tls_auth_only=yes

Make sure indentation is correct: the line submission inet ... has no leading spaces, each -o line is indented by at least one space.

Then restart Postfix:

sudo systemctl restart postfix

6. Configure Dovecot

6.1 Dovecot main config: /etc/dovecot/dovecot.conf

Likely references conf.d. Ensure protocols are correct:

protocols = imap pop3 lmtp

6.2 10-auth.conf

disable_plaintext_auth = yes
auth_mechanisms = plain login

!include auth-sql.conf.ext

6.3 10-master.conf

Check the service auth & service lmtp sections:

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
  user = dovecot
}

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0666
    user = postfix
    group = postfix
  }
}

This ensures Postfix can communicate with Dovecot for both AUTH and LMTP.

6.4 auth-sql.conf.ext

passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}

userdb {
  driver = static
  args = uid=vmail gid=vmail home=/var/vmail/%d/%n
}

6.5 dovecot-sql.conf.ext

driver = mysql
connect = host=127.0.0.1 dbname=mailserver user=mail_admin password=SomeStrongPassword
default_pass_scheme = SHA512-CRYPT

password_query = SELECT username as user, password FROM mailbox WHERE username = '%u' AND active=1
Adjust pass scheme as needed if your mailbox table uses a different hash.

Restart Dovecot:

sudo systemctl restart dovecot

7. Configure Roundcube

7.1 Install Roundcube

On Ubuntu/Debian:

sudo apt-get install roundcube roundcube-core roundcube-mysql roundcube-plugins

It may prompt for initial DB config. Let it create a DB for Roundcube (separate from mailserver).

7.2 Adjust /etc/roundcube/config.inc.php

Example settings:

$config['db_dsnw'] = 'mysql://roundcube:RoundcubeDBPass@localhost/roundcube';

$config['default_host'] = 'ssl://mail.example.com:993';
$config['smtp_server']  = 'mail.example.com';
$config['smtp_port']    = 587;
$config['smtp_user']    = '%u';
$config['smtp_pass']    = '%p';
$config['smtp_secure']  = 'tls';

$config['product_name'] = 'My Webmail';
$config['des_key'] = 'ReplaceWith24RandomChars';

$config['plugins'] = array();

7.3 Make Sure the Web Server is Enabled

For Apache, ensure /etc/apache2/conf-enabled/roundcube.conf or similar is in place. Then:

sudo systemctl restart apache2

Visit http://your_server/roundcube or https://your_server/roundcube.

8. SSL Certificates with Let’s Encrypt (Optional)

If you used Let’s Encrypt:

sudo apt-get install certbot
sudo certbot certonly --apache -d mail.example.com

or with Nginx: --nginx. Then set smtpd_tls_cert_file and smtpd_tls_key_file in Postfix (and ssl_cert/ssl_key in Dovecot) to point to the Let’s Encrypt cert paths.

9. Testing the Setup

  1. Check Postfix is listening on ports 25 & 587:
sudo ss -plnt | grep ':25\|:587'
  1. Check Dovecot on ports 143/993:
sudo ss -plnt | grep ':993\|:143'
  1. IMAP test:
openssl s_client -connect mail.example.com:993
a login bob@example.com yourpassword
a logout
  1. SMTP test with swaks:
swaks --to test@otherdomain.com --from bob@example.com --server mail.example.com:587 \
      --auth LOGIN --auth-user bob@example.com --auth-password 'yourpass' --tls
  1. If it says Authentication successful and the mail is queued, you’re good.
  2. Roundcube test:

10. Managing Users

10.1 Creating a New Mail User

  • Generate a hashed password:
doveadm pw -s SHA512-CRYPT
  • Insert into MySQL:
USE mailserver;
INSERT INTO mailbox (username, password, name, maildir, quota, local_part, domain, created, modified, active)
VALUES (
  'alice@example.com',
  '{SHA512-CRYPT}$6$...',
  'Alice Smith',
  'example.com/alice/',
  0,
  'alice',
  'example.com',
  NOW(),
  NOW(),
  1
);
  • Domain must exist in the domain table.
  • That’s it—Postfix & Dovecot will pick it up immediately.

10.2 Aliases

If you want alias@domain.com to deliver into bob@domain.com:

INSERT INTO alias (address, goto, domain, created, modified, active)
VALUES (
  'alias@domain.com',
  'bob@domain.com',
  'domain.com',
  NOW(),
  NOW(),
  1
);

11. Enabling Sent Folders & Basic Roundcube Customization

11.1 Sent Folder Setup

Roundcube ? Settings ? Preferences ? Composing Messages:

  • Save sent messages ? “Sent” folder.
  • Subscribe to “Sent” in Roundcube’s Settings ? Folders.

11.2 Auto-Creation of Folders in Dovecot

/etc/dovecot/conf.d/15-mailboxes.conf example:

namespace inbox {
  inbox = yesmailbox Drafts {
    special_use = \Draftsauto = create
  }
  mailbox Sent {
    special_use = \Sentauto = create
  }
  mailbox Junk {
    special_use = \Junkauto = create
  }
  mailbox Trash {
    special_use = \Trashauto = create
  }
}

11.3 Adding an Outbox (Optional)

You can create a normal IMAP folder called “Outbox.” However, Roundcube does not queue mail there by default. If you want true “send later” or “outbox” functionality, you need a plugin or custom behavior.

12. Troubleshooting Tips

  • Check mail logs:
  • /var/log/mail.log or /var/log/maillog for Postfix & Dovecot messages.
  • /var/log/roundcube/errors.log for Roundcube logs.
  • Verify Postfix is offering AUTH:
openssl s_client -starttls smtp -connect mail.example.com:587
EHLO test
# Must see: 250-AUTH PLAIN LOGIN
  • Ensure Dovecot’s auth_mechanisms = plain login, plus the socket is at /var/spool/postfix/private/auth with correct permissions.
  • MySQL queries: use postmap -q youruser@example.com mysql:/etc/postfix/mysql-...cf to confirm Postfix sees the right maildir or alias.
  • SELinux/AppArmor: if in “enforcing” mode, may block the socket. Consider checking or disabling for testing.
  • For Roundcube issues, enable $config['smtp_debug'] = true; to see exactly how Roundcube is talking to your SMTP server.

Conclusion

You now have a complete mail server with:

  1. Postfix for SMTP inbound/outbound.
  2. Dovecot for IMAP/POP3 and user authentication (using MySQL).
  3. Roundcube providing a modern webmail interface.

You can manage new domains and users simply by inserting rows into the MySQL domain, mailbox, and alias tables. Roundcube’s settings let you control sent/drafts folders, and with Dovecot’s auto-creation, users get a straightforward mail experience. Keep an eye on your SSL certificates, watch your logs for errors, and enjoy your fully functional mail system!

Added a class   to  , Linux Servers Set Up & Management

Login to Dev Server

eg: Putty to 192.168.1.109

Install Docker:

Step 1: Uninstall Old Docker Versions (Optional, but Recommended)

If you have any old or unofficial Docker packages installed, it's best to remove them first. If you're sure you don't, you can skip this.

Bash

sudo apt-get remove docker docker-engine docker.io containerd runc

Step 2: Update Package Index and Install Prerequisites

These packages are needed to allow apt to use a repository over HTTPS and to manage software properties.

Bash

sudo apt-get update
sudo apt-get install -y \
    ca-certificates \
    curl \
    gnupg \
    lsb-release \
    software-properties-common \
    apt-transport-https

Your initial attempt at this was mostly okay but got a bit tangled later. This single command should cover the necessary prerequisites.

Step 3: Add Docker’s Official GPG Key

This key is used to verify the authenticity of the Docker packages.

Bash

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

Step 4: Set Up the Docker Stable Repository

This command adds Docker's official APT repository to your system's list of sources.

Bash

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

(Make sure there's a space after echo and before the opening double quote. This was the main issue in your attempt.)

Step 5: Update Package Index Again

Now that Docker's repository has been added, update apt's package index so it knows about the new Docker packages.

Bash

sudo apt-get update

You should see lines in the output referring to https://download.docker.com/linux/ubuntu.

Step 6: Install Docker Engine, CLI, containerd, and Docker Compose Plugin

This command installs the latest stable version of Docker and the Docker Compose plugin (which allows you to use docker compose with a space).

Bash

sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  • If you get an error here saying a package can't be found, double-check that Step 4 and 5 completed without error and that the Docker repository was indeed added and updated.

Step 7: Verify Docker Installation

Check that Docker Engine is installed and running correctly.

Bash

sudo docker run hello-world

This will download and run a small test image. If it works, you'll see a confirmation message.

Also, check the versions:

Bash

docker --version
docker compose version

(Note the space in docker compose for the plugin version).

Step 8: Manage Docker as a Non-Root User (Highly Recommended)

To avoid having to type sudo for every Docker command: a. Add your user to the docker group (the group might already exist): bash sudo usermod -aG docker ${USER} (Replace ${USER} with your actual username if it's not automatically picked up, e.g., sudo usermod -aG docker hexucation)

b. For this change to take effect, you need to log out and log back in, or you can activate the group change for your current terminal session with: bash newgrp docker (Note: newgrp docker starts a new shell. You might prefer to just open a new terminal window after logging out and back in).

c. After logging back in or starting a new session/terminal, verify you can run Docker commands without sudo: bash docker run hello-world

Follow these steps carefully, ensuring each command completes successfully before moving to the next. Pay close attention to spaces and exact commands, especially for Step 4. This should get Docker and Docker Compose (plugin) installed correctly on your Ubuntu 20.04 system.

Install Docker Compose

sudo apt install docker-compose-plugin

Verify Installation

Check if the plugin is installed:

bash

Copy code
docker compose version

Use docker compose Command

Try running your Compose file again:

bash

Copy code
docker compose up
NGINX Example
  1. Install NGINX:
bash

Copy code
sudo apt install nginx

Configure NGINX for n8n: Create a file /etc/nginx/sites-available/n8n with the following content:

nginx

Copy code
server { listen 80; server_name public-domain>; location / { proxy_pass http://localhost:5678; 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; client_max_body_size 50M; } }

Enable the site and reload NGINX:

bash

Copy code
sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx

If you get an 400 error this is the fix:

server {

  # Existing configuration...

  client_header_buffer_sTest the configuration for syntax errors:

bash

Copy code
sudo nginx -t

Reload NGINX to apply changes:

bash

Copy code
sudo systemctl reload nginx

ize 16k;

  large_client_header_buffers 4 32k;

}

Added a class   to  , Linux Servers Set Up & Management

# Install SeedDMS Guide

## Step 1: System Requirements

Ensure your server meets the following requirements:

- Ubuntu 20.04

- Apache Web Server

- PHP version 7.4 or above

- MySQL installed

- SSL certificates configured (Let's Encrypt or other)

## Step 2: Download SeedDMS

Download SeedDMS version 6.0.28 from the official website or use the following command:

```bash

wget https://sourceforge.net/projects/seeddms/files/seeddms-quickstart-6.0.28.tar.gz

```

## Step 3: Extract Files

Create the directory where you want to extract SeedDMS and extract the downloaded tarball:

```bash

mkdir /var/www/seeddms-6.0.28
sudo tar -xzvf seeddms-quickstart-6.0.28.tar.gz -C /var/www/seeddms-6.0.28 --strip-components=1

```

## Step 4: Configure Apache

Create a new Apache configuration file for SeedDMS. For example, `/etc/apache2/sites-available/seeddms.conf`:

```apache

 ServerAdmin webmaster@localhost
 DocumentRoot /var/www/seeddms-6.0.28/www
 ServerName dms.anita.flast.com.au
 ServerAlias dms.anita.flast.com.au

 
   Options Indexes FollowSymLinks
   AllowOverride All
   Require all granted
   DirectoryIndex install.php index.php
 

 ErrorLog ${APACHE_LOG_DIR}/seeddms_error.log
 CustomLog ${APACHE_LOG_DIR}/seeddms_access.log combined

```

Add the SSL configuration to your existing SSL configuration file or create a new one:

```apache


  ServerAdmin webmaster@localhost
  ServerName dms.anita.flast.com.au
  ServerAlias dms.anita.flast.com.au
  DocumentRoot /var/www/seeddms-6.0.28/www

  
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
    DirectoryIndex install.php index.php
  

  SSLEngine on
  SSLCertificateFile /etc/letsencrypt/live/anita.flast.com.au/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/anita.flast.com.au/privkey.pem
  Include /etc/letsencrypt/options-ssl-apache.conf

  ErrorLog ${APACHE_LOG_DIR}/seeddms_ssl_error.log
  CustomLog ${APACHE_LOG_DIR}/seeddms_ssl_access.log combined

```

## Step 5: Enable Apache Configuration

Enable the newly created configuration and restart Apache:

```bash
sudo a2ensite seeddms.conf
sudo systemctl restart apache2

```

## Step 6: Set Permissions

Ensure that the appropriate permissions are set for the SeedDMS directory:

```bash
sudo chown -R www-data:www-data /var/www/seeddms-6.0.28/
sudo chmod -R 755 /var/www/seeddms-6.0.28/

```

## Step 7: Install SeedDMS

Navigate to the installation script in your web browser:

```

https://dms.anita.flast.com.au/install/install.php

```

If prompted, create the `ENABLE_INSTALL_TOOL` file in the `conf` directory:

```bash

touch /var/www/seeddms-6.0.28/conf/ENABLE_INSTALL_TOOL

```

Follow the on-screen instructions to complete the installation.

## Step 8: Post Installation

After the installation is completed, remove the `ENABLE_INSTALL_TOOL` file to prevent unauthorized changes:

```bash

rm /var/www/seeddms-6.0.28/conf/ENABLE_INSTALL_TOOL

```

Log in to SeedDMS using the default credentials (`admin/admin`) and configure your system settings as needed.

## Troubleshooting

- **404 Not Found Error**: Ensure that the `DocumentRoot` and `` paths in the Apache configuration point to the correct directory where SeedDMS files are located.
- **ERR\_TOO\_MANY\_REDIRECTS**: Check the `.htaccess` file or Apache configuration for conflicting redirects. Make sure the `DirectoryIndex` is correctly specified.

- **Missing ****`create_tables-innodb.sql`**** Error**: Verify that the SQL file is present in the `/install` directory, and try running the command manually:

 ```bash

 mysql -u seeddms -p seeddms < /var/www/seeddms-6.0.28/install/create_tables-innodb.sql

 ```

Config File

   siteName = "Anita Document Management System"
   footNote = "Anita Document Management System"
   printDisclaimer = "true"
   language = "en_GB"
   theme = "bootstrap4"
   previewWidthList = "40"
   previewWidthDetail = "100"
   onePageMode="true"
  />
  
   strictFormCheck = "false"
   viewOnlineFileTypes = ".txt;.text;.html;.htm;.xml;.pdf;.gif;.png;.jpg;.jpeg;.mp4"
   enableConverting = "true"
   enableEmail = "true"
   enableUsersView = "true"
   enableFullSearch = "true"
   enableClipboard = "true"
   enableFolderTree = "true"
   expandFolderTree = "1"
   enableLanguageSelector = "true"
   stopWordsFile = ""
   sortUsersInList = ""
   enableDropUpload = "true"
   enableRecursiveCount = "true"
   maxRecursiveCount = "0"
   enableThemeSelector = "true"
   fullSearchEngine = "sqlitefts"
   sortFoldersDefault = "u"
   defaultDocPosition = "end"
   defaultFolderPosition = "end"
  />
  
   enableCalendar = "true"
   calendarDefaultView = "y"
   firstDayOfWeek = "0"
  />
  
   enableWebdavReplaceDoc="true"
  />
 
 
  
   rootDir = "/var/www/html/dms/"
   httpRoot = "/dms/"
   contentDir = "/var/www/html/dms/data/"
   stagingDir = "/var/www/html/dms/data/staging/"
   luceneDir = "/var/www/html/dms/data/lucene/"
   logFileEnable = "true"
   logFileRotation = "d"
   enableLargeFileUpload = "true"
   partitionSize = "2000000"
   dropFolderDir = "/var/www/html/dms/data/drop/"
   cacheDir = "/var/www/html/dms/data/cache/"
   backupDir = "/var/www/html/dms/data/backup"
   debugLevel="3"
  />
  
   enableGuestLogin = "false"
   enablePasswordForgotten = "false"
   restricted = "true"
   enableUserImage = "false"
   disableSelfEdit = "false"
   disableChangePassword = "false"
   passwordStrength = "0"
   passwordStrengthAlgorithm = "simple"
   passwordExpiration = "0"
   passwordHistory = "0"
   loginFailure = "0"
   autoLoginUser = "0"
   quota = "0"
   undelUserIds = ""
   encryptionKey = "XXXXXXXXXXXXXXXXXX"
   cookieLifetime = "0">
   
    
     enable = "false"
     type = "ldap"
     host = "ldaps://ldap.host.com"
     port = "389"
     baseDN = ""
     bindDN = ""
     bindPw = ""
     filter = ""
     groupField = ""
    />
    
     enable = "false"
     type = "AD"
     host = "ldap.example.com"
     port = "389"
     baseDN = ""
     accountDomainName = "example.com"
     bindDN = ""
     bindPw = ""
     filter = ""
     groupField = ""
    />
   
  
  
   ADOdbPath="/var/www/html/dms/pear" 
   dbDriver="mysql" 
   dbHostname="localhost" 
   dbDatabase="XXXXXXX" 
   dbUser="XXXXXXX" 
   dbPass="XXXXXXX" 
  />
  
   smtpServer = "localhost"
   smtpPort = "25"
   smtpSendFrom = "anita@localhost"
   smtpUser = ""
   smtpPassword = ""
  />
 
 
  
   siteDefaultPage = ""
   rootFolderID = "1"
   showMissingTranslations = "false"
  />
  
   guestID = "2"
   adminIP = ""
  />
  
   enableAdminRevApp = "false"
   versioningFileName = "versioning_info.txt"
   workflowMode = "traditional"
   enableVersionDeletion = "true"
   enableVersionModification = "true"
   enableDuplicateDocNames = "true"
   enableDuplicateSubFolderNames = "true"
   enableOwnerRevApp = "false"
   enableSelfRevApp = "false"
   presetExpirationDate = ""
   overrideMimeType = "false"
  />
  
   coreDir = ""
   luceneClassDir = ""
   contentOffsetDir = "1048576"
   maxDirID = "0"
   updateNotifyTime = "86400"
   extraPath = ""
   maxExecutionTime = "30"
   cmdTimeout = "10"
  />
  
   enableNotificationAppRev = "true"
   enableOwnerNotification = "false"
   enableNotificationWorkflow = "false"
   />
  
   pdftotext -nopgbrk %s - | sed -e 's/ [a-zA-Z0-9.]\{1\} / /g' -e 's/[0-9.]//g'
   catdoc %s
   ssconvert -T Gnumeric_stf:stf_csv -S %s fd://1
   id3 -l -R %s | egrep '(Title|Artist|Album)' | sed 's/^[^:]*: //g'
   id3 -l -R %s | egrep '(Title|Artist|Album)' | sed 's/^[^:]*: //g'
   cat %s
   html2text %s
   docx2txt %s -
  
  
   unoconv -d document -e PageRange=1 -f pdf --stdout -v '%f'|gs -dBATCH -dNOPAUSE -sDEVICE=pngalpha -dPDFFitPage -r72x72 -sOutputFile=- -dFirstPage=1 -dLastPage=1 -q - | convert -resize %wx png:- '%o'
   convert -resize %wx '%f' '%o'
   convert -resize %wx '%f' '%o'
   convert -resize %wx '%f' '%o'
   a2ps -1 -a1 -R -B -o - '%f' | gs -dBATCH -dNOPAUSE -sDEVICE=pngalpha -dFirstPage=1 -dLastPage=1 -dPDFFitPage -r72x72 -sOutputFile=- -q - | convert -resize %wx png:- '%o'
  
 <server
 rootDir="/var/www/seeddms-6.0.28/"
 httpRoot="/"
 contentDir="data/"
 stagingDir="data/staging/"
 luceneDir="data/lucene/"
 logFileEnable="true"
 logFileRotation="d"
 enableLargeFileUpload="true"
 partitionSize="2000000"
 dropFolderDir="data/drop/"
 cacheDir="data/cache/"
 backupDir="data/backup"
 ADOdbPath="/var/www/seeddms-6.0.28/pear"
/>

database
 type="mysql"
 host="localhost"
 database="seeddms"
 user="seeddms"
 password="your_password_here"
/>
  

 

Added a class   to  , Linux Servers Set Up & Management

Proxmox VM Network

Subnet = IP with .0/24 not 255.255.255.0/24

Gatway is .254 always

Network with Bridge

edit /etc/netplan

copy and back up existing file.

create a new file with nano

insert :

network:
  version: 2
  ethernets:
    eno3:
      dhcp4: no # Disable DHCP since you have static IPs
      addresses:
        - 142.44.212.192/24 # Your main static IP
        - 54.39.92.189/32  # Additional IP 1
        - 54.39.92.191/32  # Additional IP 2
        - 54.39.118.47/32  # Additional IP 3
        - 54.39.118.48/32  # Additional IP 4
        - 2607:5300:203:25c0::1/64
      routes:
        - to: 0.0.0.0/0  # Default IPv4 route
         via: 142.44.212.254
        - to: ::/0  # Default IPv6 route
         via: 2607:5300:203:25ff:ff:ff:ff:ff # Or your actual IPv6 gateway
      nameservers:
        addresses: [8.8.8.8, 1.1.1.1, 2001:41d0:3:163::1]
      accept-ra: false
      match:
        macaddress: 0c:c4:7a:c8:76:ae

Ping to test

ping -I 54.39.92.191 8.8.8.8 
Added a class   to  , Linux Servers Set Up & Management

For example you have been assigned :

54.39.92.191

and

54.39.92.189

Here is ip a readout:

root@contractout:/var/lib/vz/template/iso# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group defaul                                                                                                                                                                                                                                             t qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eno3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master vmbr0 state                                                                                                                                                                                                                                              UP group default qlen 1000
    link/ether 0c:c4:7a:c8:76:ae brd ff:ff:ff:ff:ff:ff
    altname enp3s0f0
3: eno4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen                                                                                                                                                                                                                                              1000
    link/ether 0c:c4:7a:c8:76:af brd ff:ff:ff:ff:ff:ff
    altname enp3s0f1
4: vmbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP grou                                                                                                                                                                                                                                             p default qlen 1000
    link/ether 0c:c4:7a:c8:76:ae brd ff:ff:ff:ff:ff:ff
    inet 142.44.212.192/24 scope global vmbr0
       valid_lft forever preferred_lft forever
5: tap100i0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast                                                                                                                                                                                                                                              master fwbr100i0 state UNKNOWN group default qlen 1000
    link/ether 2e:71:17:63:af:19 brd ff:ff:ff:ff:ff:ff
6: fwbr100i0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP                                                                                                                                                                                                                                              group default qlen 1000
    link/ether 5a:40:8e:1b:8a:e7 brd ff:ff:ff:ff:ff:ff
7: fwpr100p0@fwln100i0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue                                                                                                                                                                                                                                              master vmbr0 state UP group default qlen 1000
    link/ether be:6d:0e:18:91:8d brd ff:ff:ff:ff:ff:ff
8: fwln100i0@fwpr100p0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue                                                                                                                                                                                                                                              master fwbr100i0 state UP group default qlen 1000
    link/ether 5a:40:8e:1b:8a:e7 brd ff:ff:ff:ff:ff:ff
root@contractout:/var/lib/vz/template/iso# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eno3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master vmbr0 state UP group default qlen 1000
    link/ether 0c:c4:7a:c8:76:ae brd ff:ff:ff:ff:ff:ff
    altname enp3s0f0
3: eno4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 0c:c4:7a:c8:76:af brd ff:ff:ff:ff:ff:ff
    altname enp3s0f1
4: vmbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 0c:c4:7a:c8:76:ae brd ff:ff:ff:ff:ff:ff
    inet 142.44.212.192/24 scope global vmbr0
       valid_lft forever preferred_lft forever
5: tap100i0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master fwbr100i0 state UNKNOWN group default qlen 1000
    link/ether 2e:71:17:63:af:19 brd ff:ff:ff:ff:ff:ff
6: fwbr100i0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 5a:40:8e:1b:8a:e7 brd ff:ff:ff:ff:ff:ff
7: fwpr100p0@fwln100i0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master vmbr0 state UP group default qlen 1000
    link/ether be:6d:0e:18:91:8d brd ff:ff:ff:ff:ff:ff
8: fwln100i0@fwpr100p0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master fwbr100i0 state UP group default qlen 1000
    link/ether 5a:40:8e:1b:8a:e7 brd ff:ff:ff:ff:ff:ff

Next you need to :

sudo nano /etc/network/interfaces
  1. Add the new IP addresses: Add the new IP addresses to the vmbr0 interface. Your configuration should look something like this:
auto lo
iface lo inet loopback

iface eno3 inet manual

auto vmbr0
iface vmbr0 inet static
    address 142.44.212.192/24
    gateway 142.44.212.254
    bridge-ports eno3
    bridge-stp off
    bridge-fd 0
    hwaddress 0C:C4:7A:C8:76:AE

iface vmbr0 inet6 static
    address 2607:5300:203:25c0::1/128
    gateway 2607:5300:203:25ff:ff:ff:ff:ff

# Add the new IP addresses here
up ip addr add 54.39.92.191/24 dev vmbr0
up ip addr add 54.39.92.189/24 dev vmbr0

ave and exit: Save the file and exit the text editor (in nano, you can do this by pressing Ctrl+X, then Y, and Enter).

Restart the networking service: Restart the networking service to apply the changes:

sudo systemctl restart networking

Verify the new IP addresses: Check if the new IP addresses have been added successfully:

ip addr show vmbr0

This should add the two new IP addresses to your vmbr0 interface.

Added a class   to  , Linux Servers Set Up & Management

Proxmox

SSH in 

su - = root

apt-get update = first time it may error 

root@contractout:~# rm /etc/apt/sources.list.d/pve-enterprise.list

root@contractout:~# nano /etc/apt/sources.list

root@contractout:~# apt-get update

Now let's give the user access:

root@contractout:~# usermod -aG sudo danny

root@contractout:~# sudo whoami root

root@contractout:~# sudo systemctl restart pveproxy.service

root@contractout:~# sudo systemctl restart pvedaemon.service

root@contractout:~# pveum user add danny@pam

root@contractout:~# pveum acl modify / --roles PVEAdmin --users danny@pam

Upload Images Directly 

root@contractout:~# cd /var/lib/vz/template/iso/

root@contractout:/var/lib/vz/template/iso# ls

root@contractout:/var/lib/vz/template/iso# wget https://releases.ubuntu.com/20.04.6/ubuntu-20.04.6-live-server-amd64.iso

Added a class   to  , Linux Servers Set Up & Management
Added a class   to  , Linux Servers Set Up & Management

To clone your private repository to another server, you'll need to use a method that allows authentication. Here are the two main approaches:

1. SSH (Recommended):

This is the most secure and convenient way to clone a private repository.

Prerequisites:

  • SSH Key Pair on the New Server: Generate an SSH key pair on the server where you want to clone the repository (if it doesn't have one already). You can use ssh-keygen for this.
  • Public Key Added to GitHub: Make sure the public key from the new server is added to the list of "SSH and GPG keys" in your GitHub account settings.

Steps:

  1. Get the SSH URL:
  • Go to your GitHub repository.
Click the "Code" button and select the "SSH" tab to copy the SSH URL. It should look like this:git@github.com:cr0atz/flast-ai-v5.1.git
  1. Clone the Repository:
  • On the new server, open a terminal and run:Bash
git clone git@github.com:cr0atz/flast-ai-v5.1.git
  • content_copy
  • This will clone the repository using SSH authentication.

2. Personal Access Token (PAT):

This method is an alternative if you don't want to use SSH keys.

Prerequisites:

  • Personal Access Token (PAT): Generate a PAT in your GitHub account settings with the "repo" scope.

Steps:

  • Clone the Repository:On the new server, run the following command, replacing <your_pat> with your actual PAT:Bash
git clone https://<your_pat>@github.com/cr0atz/flast-ai-v5.1.git
  • content_copy
  • This will prompt you for your GitHub username (which you can enter). Git will use the PAT you've included in the URL for authentication.

Important Considerations:

  • HTTPS vs. SSH: The SSH method uses the git@github.com URL, while the PAT method uses the https://github.com URL.
  • Security: SSH keys are generally more secure than embedding your PAT directly in the URL.
  • 2FA: If you have two-factor authentication (2FA) enabled on GitHub, you'll be prompted for a 2FA code during the cloning process if you use the PAT method.

Additional Tips:

  • Virtual Environments: If your project uses a virtual environment, remember to create and activate a new virtual environment on the new server before installing dependencies.
  • Troubleshooting: If you encounter permission errors, ensure that the user running the git clone command has the necessary permissions to create the repository directory and files on the new server.

Let me know if you have any other questions!

Added a class   to  , Linux Servers Set Up & Management

First of all if running the YT - transcriber we need to make sure the service is running within the venv environment.

[Unit]
Description= flastai engine client
After=network.target

[Service]
User=flastai
WorkingDirectory=/var/www/html/BlogEngine_v5.0/

# ExecStart=/var/www/html/BlogEngine_v5.0/venv/bin/streamlit run home.py --server.port 30000
ExecStart=/bin/bash -c 'source venv/bin/activate && /var/www/html/BlogEngine_v5.0/venv/bin/streamlit run home.py --server.port 30000'

Restart=always

[Install]
WantedBy=multi-user.target

New Code (inside home.py) :

class Document:
    def __init__(self):
        self.text = ""


    def set_text(self, text):
        self.text = text


def transcribing_function(video_id):
    st.warning("Transcribing video...")


    
    # Define the path to the Whisper model files and audio folder
    whisper_model_path = f"../{folder_root}/"
    audio_path = f"{folder_audio}/{video_id}.mp3"
    
    # Execute yt-dlp command to download and convert video audio to mp3
    result = subprocess.run(
        [yt_dlp_path, '-f', 'bestaudio', '-o', audio_path, f"https://www.youtube.com/watch?v={video_id}"],
        capture_output=True,
        text=True
    )
    
    # Check for errors in the subprocess execution
    if result.returncode != 0:
        st.error("Failed to download and convert video.")
        st.error(result.stderr)
        return


    # Load Whisper model
    model = whisper.load_model("base.en", download_root=whisper_model_path)


    # Transcribe the audio file
    try:
        transcription_result = model.transcribe(audio_path)
        text = transcription_result['text'].strip()
    except Exception as e:
        st.error(f"Error transcribing video: {str(e)}")
        return


    # Split the text into parts
    max_chars = 28000
    parts = [text[i:i + max_chars] for i in range(0, len(text), max_chars)]
    docs = []
    for part in parts:
        doc = Document()
        doc.set_text(part)
        docs.append(doc)


    # Save each part to a separate file
    for i, doc in enumerate(docs):
        filename = os.path.join(folder_files, f"transcribed-{video_id}_{i}.txt")
        with open(filename, "w", encoding="utf-8") as f:
            f.write(doc.text)
        st.success(f"Transcribed chunk_{i} saved.")


    # Assuming right_column is defined correctly elsewhere
    with right_column:
        # Get and display transcribed files
        transcribed_files = [file for file in os.listdir(folder_files) if file.endswith(".txt") and video_id in file]
        if not transcribed_files:
            st.error("No transcribed files found.")
            return


        st.success("Video transcribed and split into parts successfully.")
        num_columns = min(len(transcribed_files), 3)
        columns = st.columns(num_columns, gap="small")


        for i, column in enumerate(columns):
            for j in range(i, len(transcribed_files), num_columns):
                file_path = os.path.join(folder_files, transcribed_files[j])
                with open(file_path, "rb") as f:
                    contents = f.read()
                    encoded = base64.b64encode(contents).decode()
                    href = f'<a href="data:application/octet-stream;base64,{encoded}" download="{transcribed_files[j]}" target="_blank">{transcribed_files[j]}</a>'
                    column.markdown(href, unsafe_allow_html=True)


        with st.expander("Transcribed files (Click to hide/unhide text)"):
            for filename in transcribed_files:
                with open(os.path.join(folder_files, filename), "r") as file:
                    file_contents = file.read()
                    st.success(f"File name: {filename}\n\n{file_contents}")


    return docs

Configuration - Requirements.

Activate the virtual environment:

Bash

 source /var/www/html/BlogEngine_v5.0/venv/bin/activate

Uninstall Whisper:Bash

pip uninstall whisper

Increase memory

sudo mount -o remount,size=6G /tmp

Reinstall Whisper: Make sure you're installing the latest version.

pip install -U openai-whisper --no-cache-dir

IMREAL.LIFE

Close