Script to install Proxmox 7.x – 8.x on a Dedicated Hetzner Server

The Proxmox-Version depends on your OS: Proxmox 7.x on Debian Bullsey and Proxmox 8.x on Debian Bookworm.

  • Install Proxmox on your server
  • Let’s Encrypt Certificate for the Proxmox-Interface
  • Option to use Thin-Pool Storage
  • Read the Server-IPs (Single-IP and Subnet) from the Hetzner-Robot
  • Write the Network-Config
  • Option to create private IPs if you use a vSwitch

Notes

You can put your Robot-Credentials in the file robot.conf.php so the script will not ask your for the Robot-Login.

If you just want to generate the network config (even for a different server), see chapter Network-Setup at the end of this page

Installation

Boot your server into the Rescue-Mode, use installimage and choose the minimal Debian Bullseye or Debian Bookworm Version.

Set the HOSTNAME to a FQDN

If you want to use Thin-Pool, use something like:

PART lvm pve all
LV   pve root / ext4 10G

Reboot the server and run the following commands to download the script:

apt -y update
apt -y install php-cli php-curl wget
cd /root
wget https://download.schaal-it.net/hetzner-proxmox.tgz
tar xfz hetzner-proxmox.tgz
cd proxmox

Install Proxmox

To install Proxmox, please read the following notes before running the script.

The directory custom contains several files that are used during the installation.

In the custom directory you will find:

  • etc/aliases
  • etc/cron.d/trim.example
  • etc/sysctl.d/pve.conf
  • root/trim.sh.example
  • root/update-lxc.sh.example
  • ssh (empty)

If you want to install your ssh-key, just put your public-key into ssh/authorized_keys. The installer will copy this file to /root/.ssh/authorized_keys

The files from etc/cron.d calls the responding scripts from root. If you want to use them, rename the file in etc/cron.d and root.

You can also put your own files into the custom-dir and / or change the files. For more informations see the file custom/README.txt.

To finally install proxmox, just run

php install-proxmox.php

The script shows you the detected OS and the Proxmox-Version, that will be installed:

Detected OS: Debian Bookworm
Install Proxmox-Version: 8.x

You will be asked the following questions:

Full qualified hostname (FQDN) of the server [server]:

Add the full name here (i.e. server.example.com). Otherwise you can not use Let’s Encrypt.

IP of the server [100.150.0.100]:

Make sure that the recognized ip is also the one from your server

Network Card [enp0s31f6]:

Usually, you don’t have to change the detected value.

Do you want to autoconfigure the network? (y,n) [y]:

Choose y to let the script generate the network-config.

Enter your credentials for the Hetzner-API
robot_url [https://robot-ws.your-server.de]:
robot_user []: 
robot_password []:

Enter your robot-credentials if you did not already stored them in robot.conf.php.

Enabled Thin-Pool for Proxmox? (y,n) [n]:

With y the installer will generate a Thin-Pool:

Only one LV found - using pve
Use LV Name for Proxmox Thin-Pool - 'none' to skip [data]:
SSH Port [22]:
SSH PremitRootLogin [yes]:

You you should use the defaults for a Cluster-Setup.

Use Let's Encrypt for the Interface (y,n) [y]:

Choose y if you want a free ssl-cert from Let’s Encrypt for the Backend.

Email to use with Let's Encrypt and in scripts [admin@local]:

Start Proxmox Install? (y,n) [y]:

Finally run the setup.

If your server is connected to a vSwicth:

This server is connected to the vswitch with the ID 4868 [4001]
Add the vswitch to the network-config? (y,n) [y]:
Use Private IP []:
Use Private IP []: 
Netmask [24]:

Choose a private IP like 10.0.0.1 for this server and set the netmask.

copy /etc/network/interfaces to /root/interfaces.save
writing new /etc/network/interfaces

Check the network-confg and reboot your server
Updating /etc/aliases
Adding your authorized_keys

Install finished. You can reboot the server now.

Network-Setup

You can also use network-manual.php to generate a network-config on an existing server.

This will not overwrite your current setup.

Run

php network-manual.php

and answer the questions. You find the generated config in /root/interfaces.generated

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

Bugtracker

Visit our issue tracker.

Monitoring

,

You always have full access to the monitoring of your managed server and can view the data directly in your browser or via your smartphone.

If the state changes, you will receive a mail after a certain time. You will get the notification if the status changes to OK, Warn or Crit.

Browser

Just open the URL https://monitor.schaal-server.de for monitoring in your browser and log in with your access data.

Smartphone APPs

aNag for Android

Grab aNag from the the playstore and start the App.

You can freely choose the name – it only serves to distinguish between different instances.

The other data are:
Instance type: Icinga/Nagios (HTML) 
URL: https://monitor.schaal-server.de/managed/nagios/cgi-bin/ 
Username: Your Username  
Password: Your Password

easyNag for iPhone & iPad

You can download and install easyNag here.

You can use the settings for Android for the individual values.

Manage PHP versions

,

You can install an available PHP version or delete an installed PHP version on our managed servers at any time.

Install PHP-Version

To install a PHP version, open the “System” section in ISPConfig and select “PHP Versions” on the left.

 

Use the button “Install new PHP version” to install the PHP versions you are missing.

 

Delete PHP version

If you no longer need a PHP version on your server, you can delete it directly in the overview of the installed PHP versions.

Deleting a version is only possible if it is not used by any website and is not the default version for new websites.

By the way, you can change the default version for new websites at any time in the server configuration in the “Web” section under “PHP settings”.

 

Joomla with Redis Object Cache

In the following text we will show you how to speed up an already existing Joomla installation with a Redis cache.

If you install a new Joomla with our web wizard, you can also install and activate the Redis cache automatically.

Create a Redis Instance

Log in to ISPConfig on your managed server. In the Sites section you will find the item Redis Databases under Databases on the left. Select this item and create a new Redis-Instance.

 

You just need to select the appropriate website and assign a suitable name for the Redis instance. You can leave the policy unchanged.

The max. database size also depends on the number of visitors. You can start with the default 128 MB and adjust this value later.

After you have created the new instance, open it in ISPConfig and write down the Redis Port and the Redis Password.

Configure Joomla

Once you have logged into Joomla, open the Global Configuration section, select the System section and enable the cache.

You can use Redis as cache for the site and / or for the sessions.

The settings are identical in both cases.

You have to set the value of Redis Server Port and Redis Server Authentication according to the created Redis instance.

The values for the Redis cache can also be displayed on the website in ISPConfig by clicking on “Show Redis-Config”.

WordPress with Redis Object Cache

In the following article we will show you how to speed up an existing WordPress with a Redis cache.

If you install a new WordPress with our web wizard, you can also install and activate the Redis cache automatically.

Create a Redis Instance

Log in to ISPConfig on your managed server. In the Sites section you will find the item Redis Databases under Databases on the left. Select this item and create a new Redis-Instance.

 

You just need to select the appropriate website and assign a suitable name for the Redis instance. You can leave the policy unchanged.

The max. database size also depends on the number of visitors. You can start with the default 128 MB and adjust this value later.

After you have created the new instance, open it in ISPConfig and write down the Redis Port and the Redis Password.

Install plugin in wordpress

Install the Redis Object Cache plugin in your Worpress.

 

Plugin set up in WordPress

The required data is entered into the wp-config.php of your website. You can download the file via FTP, adjust it and upload it again.

In the wp-config.php you have to enter some values for the Redis cache. Search for the line

/* That's all, stop editing! Happy blogging. */

and then insert these lines:

define( 'WP_REDIS_HOST', '127.0.0.1' );
define( 'WP_REDIS_PORT', '6380' );
define( 'WP_REDIS_PASSWORD', '229cf27de2e025771a087484f46fff');
define( 'WP_REDIS_TIMEOUT', 1 );
define( 'WP_REDIS_READ_TIMEOUT', 1 );
define( 'WP_REDIS_DATABASE', 0 );

You have to set the values of WP_REDIS_PORT and WP_REDIS_PASSWORD according to the created Redis instance.

The values for the Redis cache can also be displayed on the website in ISPConfig by clicking on “Show Redis-Config”.

Activate the plugin in WordPress

Now you just have to activate the plugin and click on “Enable Object Cache”.

Customize system mails

,

Our managed servers send mails under different conditions. Probably the most important part are the notifications about the used disk space.

Manage system mails

You can customize these messages and add new languages. To do this, select “System Mails” in the “System” section at the bottom left.

Customize system mails

To customize a message according to your wishes, select the corresponding mail:

You can customize the subject and the text of the message.

Important Messages with the language “en” can neither be deleted nor deactivated, because they are only used if no other template is found.

Create a new system mail

If you click on the + symbol on the right side of the message, you can create the message in another language.

Usage of new system mails

When the server sends a notification (e.g. quota notifications), the corresponding template is determined in the following order:

  • Template that matches the customer’s language (see Customers / Language) and is active.
  • Template that matches the language English

Setting up HSTS for a website

,

What is HSTS?

HTTP Strict Transport Security (HSTS) is an instruction from the web server that informs the web browser (or other programs) how the connection between the server and the web browser should be handled. This information is sent right at the beginning in the so called “Response Header”.

A simple redirection from HTTP to HTTPS can still be bypassed. The “Strict-Transport-Security” parameter forces the web browser to establish the connection encrypted over HTTPS, ignoring any script that wants to load resources of the domain over HTTP. This means that, for example, cookies or session IDs of the website cannot be collected, nor can the website be redirected to a phishing site.

Why use HSTS?

  • HSTS is a way to increase the security of the connection to your website.
  • The increased security can also have a positive effect on Google’s ranking.

What are the requirements for HSTS?

  • valid SSL certificate for the website and all other subdomains
  • Redirection of all requests from HTTP to HTTPS
  • HSTS max-age must be at least 1 year
  • HSTS includeSubDomains must be enabled
  • HSTS preload must be enabled

What do the individual values for HSTS mean?

HSTS max-age

Time in seconds during which the web browser considers the web page to be a known HSTS host and does not establish connections over HTTP.

HSTS includeSubDomains

Ensures that the HSTS policy is applied not only to the domain, but also to all sub-domains, e.g. example.com and www.example.com.

HSTS preload

Whether to include the web page in the HSTS preload list maintained by Chrome (and used by Firefox and Safari, IE 11, and Edge). When HSTS preload is active, the web browser is forced to access the page over HTTPS because the web browser knows in advance that this page can only be accessed over HTTPS.
Sending the preload directive can cause problems and prevent users from accessing the web page and its subdomains if you reset the page to HTTP.
If HSTS preload is active, you can add your website to the list maintained by Chrome at https://hstspreload.org.

Test HSTS with a website

Before you “arm” HSTS for your website, you should first test your site with HSTS. The following requirements must be met for a test:

  • valid SSL certificate for the website and all other subdomains
  • Redirection of all requests from HTTP to HTTPS

On our managed servers, you can only activate HSTS if you have also set up a valid SSL certificate for the website. Other requirements will be automatically adjusted when you enable HSTS.

If you have activated HSTS, set “HSTS max-age” to one week first for testing purposes to be able to detect any problems. If the test phase is successful and without problems, you can set “HSTS max-age” to one month and extend your tests, or you can activate HSTS completely.

Enable HSTS for a website

If your website has a valid SSL certificate, you can enable HSTS. Log in to ISPConfig and open the corresponding website. Under “Advanced options” you will find the appropriate settings:

 

Use cron snippets

,

Cron snippets work similar to the directive snippets for web pages. These are predefined cron jobs that can be selected when creating a cron job under “Cron Snipet” or in the settings for the web wizard.

Show Cron Snippets

You can find predefined cron snippets in the “System” section under “Cron snippets”.

Create Cron Snippet

To create a new template, select “Add cron snippet”. You will then see the following screen:

Use “Name of Snippet” to set the name that should appear under “Cron template” for the cron jobs.

The values (time and command) are identical to the cron jobs.

With “Cronjob active” you control if the cron job created with this snippet should be set to active. “Active” means that this snippet is displayed in the cron snippet list. If you disable “Customer viewable”, you can only see and use it as admin in the cron snippet list.

Use Cron Snippet

As a client, only the cron snippets that match the cronjob limit (URL, Chrooted, Full) are displayed. As admin you can of course use any snippet for a cronjob and create the corresponding cron job.

Cron Snippets Group

You can combine several cron snippets into one group and create all cron jobs from one group in the settings for the web wizard for a CMS.

Password check with haveibeenpwned

,

The website haveibeenpwned.com provides, among other things, a list of passwords that have appeared in data leaks.

haveibeenpwned is secure

For verification, the complete password is never sent, but only a small partial hash value.

The pwned passwords function used searches the database of previous data leaks for the presence of a user-supplied password. The password is hashed using the SHA-1 algorithm and only the first 5 characters of the hash are sent.

Integration with ISPConfig

In the Main Config section you can set the maximum number of entries a password may have when querying the haveibeenpwned database in the “Misc” tab.

If a password is entered that is in the database more times than you have allowed, a hint is displayed and the password cannot be used.

Nextcloud with Chrooted-User and Cron-Job

,

These instructions do not apply to a Nextcloud installation that you created via the wizard – the wizard creates the corresponding file automatically.

If you want to execute the command ‘php occ …’ as a “limited” shell user (chrooted shell = jailkit), you have to make two changes to the Nextcloud configuration. We use our own configuration for this, which is not overwritten during an update and automatically detects whether a request is made via the shell or the website.

On our managed servers, you can view the custom.config.php directly in ISPConfig for the specific website and upload it directly to the config folder via FTP.

This guide only says shell, but that all applies to cron jobs running ‘chrooted’ as well.

To find the mode in which a cron job is executed, open the corresponding cron job in ISPConfig:

In the following example, our website is installed with Nextcloud in the directory /var/www/clients/client3/web1602/web. You can find the directory in ISPConfig for a website in the first part of “Different Document Root” when you open the “Advanced” section.

Adjust values in the Nextcloud configuration

  1. datadirectory
    A chrooted shell user cannot access the complete path of the web page /var/www/clients/client3/web1602/web. Therefore the datadirectory must be “rewritten” if you want to execute “php occ” via the shell. We simply use a custom.config.php for this.
    dbhost
  2. You can not use localhost as the dbhost. PHP uses a connection via the socket file with localhost, because such a connection is the fastest. But in a chrooted shell the socket file is not available and you get the error “Doctrine\DBAL\Exception: Failed to connect to the database”. Either you change the ‘dbhost’ in config.php from ‘localhost’ to ‘127.0.0.1’ (then the connection is always over TCP/IP is slower) or you simply use our custom.config.php.

Create custom.config.php

In the config directory of the Nextcloud installation, create the file custom.config.php or create it on your PC and then upload the created file via FTP into the config directory.

You only need to adjust two values in the custom.config.php for your Nextcloud installation:

$basedir – here you enter the path to your website as it is displayed in ISPConfig and only leave out ‘/web’ at the end.
$dir – this sets the data directory of Nextcloud. In most installations the data directory is located in the document root of the website. If you log in via FTP, you can easily find the directory:

The custom.config.php looks like this in our example:

<?php
$basedir = '/var/www/clients/client3/web1601';
if(php_sapi_name() != 'cli') {
  $dir = $basedir;
} else {
  $dbhost = '127.0.0.1';
  $dir = (!is_dir($basedir)) ? '' : $basedir;
}
$dir .= '/web/data';
$CONFIG['datadirectory'] = $dir;
if($dbhost !== null) $CONFIG['dbhost'] = $dbhost;