From: Brian Flowers <git-admn@bsflowers.net> Date: Sat, 24 Apr 2021 02:30:01 +0000 (-0400) Subject: Initial commit X-Git-Url: http://git.slightlycyberpunk.com%2C%20git.slightlycyberpunk.com/git/?a=commitdiff_plain;h=8497add7a0a8f50d42f3a0f38a551b13fb3e712f;p=tutorials.git Initial commit --- 8497add7a0a8f50d42f3a0f38a551b13fb3e712f diff --git a/centos_dovecot.html b/centos_dovecot.html new file mode 100755 index 0000000..1efc699 --- /dev/null +++ b/centos_dovecot.html @@ -0,0 +1,579 @@ +<html> + <head> + <title>Dovecot on Centos 7</title> + <script src="/scripts/charNames.js" ></script> + <link rel="icon" type="image/png" href="/favicon.png"> + <meta name="title" content="Dovecot on Centos 6"> + <meta name="description" content="Installing and configuring Dovecot and + E-mailrelay as an intermediate mail server on a Centos 6 VM."> + <style> + pre + { + background-color: #DDD; + padding: .5em .75em; + margin: 0em; + font-weight: 600; + } + + .filename + { + margin-bottom: 0em; + padding-bottom: 0em; + background-color:#CCCCCC; + font-weight: bold; + padding: .2em .5em; + font-size: 1.1em; + } + + .filename:before + { + content: "nano "; + } + + .TODO + { + background-color: #DD5; + font-weight: bold; + } + + .var + { + color: #383; + font-weight: bold; + } + + .suggested + { + color: #AA0; + font-weight: bold; + } + + .security + { + color: #C44; + font-weight: bold; + } + </style> + </head> + +<body> + +<h1>Legend</h1> +<p> +<span class="todo">Work in progress</span><br> +<span class="var">Installation specific values</span><br> +<span class="suggested">SC standard configuration</span><br> +<span class="security">Security configuration</span> +</p> + +<h1>Base System Setup</h1> +<p>Update the OS and install dovecot and (optionally) nano</p> +<pre> +yum update +yum install sudo nano wget mailx dovecot procmail fetchmail +</pre> + +<p>Create required user accounts.</p> +<p>For the fetchmail filtering described in the + next step, you may also want to create the users <span class="suggested"> + spam</span> and <span class="suggested">pending</span></p> +<pre> +useradd <span class="var"><username></span> -m -d /home/<span class="var"><username></span> -s /bin/bash +usermod -a -G mail <span class="var"><username></span> +su - <span class="var"><username></span> +</pre> + +<h1>Configure Fetchmail</h1> +<p>Create required files:</p> +<pre> +touch /home/<span class="var"><username></span>/.fetchmailrc +chmod 0600 /home/<span class="var"><username></span>/.fetchmailrc +touch /etc/init.d/fetchmail +chmod +x /etc/init.d/fetchmail +</pre> + +<p>Create mail filter (if desired).</p> +<p>The filter shown below has a number of different features. Each block can be removed if + not required. Read the script comments for details.</p> +<p>The first block is spam filtering by address -- any messages sent to an address listed + in the file /etc/mailblock.lst (one address per line) will be filtered and delivered to + the 'spam' user. You should have a 'spam' user setup the same as your other mail + accounts to use this feature.</p> +<p>The second block is two-step verification filtering -- any messages sent to an address + listed in the file /etc/mailverify.lst will be held for verification. To use this feature, + you must configure a user 'pending' as well as a wildcard alias on '*-pending'. When a + message is delivered for one of the designated addresses, it will be stored with a randomly + generated ID number and a message will be sent to the sender from the address '<random>-pending'. + When the user replies to that mail, their original message will be sent to the address + originally provided</p> +<p class="filename">/etc/mailDelivery.sh</pre> +<pre> +# The destination user can be selected either by an argument to the script, +# or based on the user who is executing the script +user="${1}" +if [ -z "${user}" ]; then + user=`whoami` +fi + +# Read the message and filter the destination addresses from it +# The addresses will have "^" and "$" characters added to the start and end +# for later grep commands. +message=$(cat; echo x) +address="`echo -n \"${message%x}\" | \ + grep -e '^To: ' -e \$'^[ \t]*for' | \ + awk '{print \"^\"$2\"\$\"}' | \ + sed 's/[\"<>;]//g'`" + + + + +# If a blacklist is provided at /etc/mailblock.lst, messages sent to that address +# will be redirected to the inbox of the "spam" user +if [ `cat /etc/mailblock.lst | grep -ic "${address}"` -gt 0 ]; then + user="spam" + + + +# If a list is provided at /etc/mailverify.lst, messages sent to those address +# will require additional verification before being delivered. +# A mail account must be configured for the 'pending' user, with a wildcard alias +# configured on *-pending@<span class="var">domain</span> +elif [ `cat /etc/mailverify.lst | grep -ic "${address}"` -gt 0 ]; then + # First, generate a random ID number to identify this message + idnum=$((RANDOM)) + attempts=0 + if [ ! -d /home/pending/messages/ ]; then + mkdir -p /home/pending/messages/ + fi + + # If the number is already used, retry up to ten times + while [ -f /home/pending/messages/$idnum.msg ] && [ $attempts -lt 10 ]; do + idnum=$((RANDOM)) + attempts=`expr $attempts + 1` + done + + # If we could not find a free number, fail to deliver + # The user will be sent the contents of /home/pending/failure.msg + # and their original message + if [ $attempts -eq 10 ]; then + echo "FAILURE" + msg=$(cat /home/pending/failure.msg) + echo "${msg} ${message}" | mailx -v \ + -s "Your message could not be delivered" \ + -S smtp-auth=cram-md5 \ + -S smtp=smtp://mail.<span class="var">domain</span>:10025 \ + -S from="<span class="var">domain</span> pending messages <$idnum-pending@<span class="var">domain</span>>" \ + -S smtp-auth-user=pending \ + -S smtp-auth-password='<span class="var">password</span>' \ + -S nss-config-dir="/etc/pki/nssdb/" \ + -S ssl-verify=warn \ + -S smtp-use-starttls \ + "${from}" + exit 1 + fi + + # Save the message, and give all mail users permission to access it + # This is required so it can be accessed by the correct destination user + echo -n "${message%x}" > /home/pending/messages/$idnum + chown `whoami`:mail /home/pending/messages/$idnum + chmod 660 /home/pending/messages/$idnum + + # Get the sender's address from the message, and send them the contents of + # /home/pending/autoresponse.msg, with their message attached. The message + # will be sent from the address <random number>-pending@<span class="var">domain</span> + # and will be released when a reply is received to the same address + from="`cat /home/pending/messages/$idnum | \ + grep '^From:' | \ + cut -d':' -f2- | \ + sed 's/[^@]*[ <]\([^ ]*@[^ ]*\)[^@]*/\1/g' | \ + sed 's/[\"<>;]//g'`" + cat /home/pending/autoresponse.msg | mailx -v \ + -a /home/pending/messages/$idnum \ + -s "Action required: Your message was not delivered" \ + -S smtp-auth=cram-md5 \ + -S smtp=smtp://mail.<span class="var">domain</span>:10025 \ + -S from="<span class="var">domain</span> pending messages >$idnum-pending@<span class="var">domain</span>>" \ + -S smtp-auth-user=pending \ + -S smtp-auth-password='<span class="var">password</span>' \ + -S nss-config-dir="/etc/pki/nssdb/" \ + -S ssl-verify=warn \ + -S smtp-use-starttls \ + "${from}" + exit 0 + +# If a reply is received to a *-pending@<span class="var">domain</span> address, +# send the saved message instead +elif [ `ls /home/pending/messages/ | sed 's/$/-pending@bsflowers.net/g' | grep -ic "${address}"` -gt 0 ]; then + idnum="`echo \"${address}\" | \ + sed 's/\^\([0-9]*\)-pending.*/\1/' | \ + sort -u | \ + grep -v [^0-9]`" + destination="`cat /home/pending/messages/$idnum | \ + grep -e '^To: ' -e \$'^[ \t]*for' | \ + awk '{print \"^\"$2\"\$\"}' | \ + sed 's/[\"<>;]//g'`" + + user=`echo $destination | cut -d '@' -f1 | cut -d'-' -f2 | sed 's/^^//g'` + cat /home/pending/messages/$idnum | sudo /usr/bin/procmail -d $user + rm /home/pending/messages/$idnum + exit 0 +fi + + + +# Useful for debugging -- saves a copy of each message in the user home +# echo -n "${message%x}" > /home/$user/mail.tmp + +# Send the message +echo -n "${message%x}" | sudo /usr/bin/procmail -d $user +</pre> + +<p class="filename">/etc/mailblock.lst</p> +<pre> +spammy-address@<span class="var">domain</span> +</pre> + +<p class="filename">/home/<span class="var"><username></span>/.fetchmailrc</p> +<pre> +set daemon <span class="suggested">300</span> +poll <span class="var"><external mailserver></span> with proto <span class="suggested">pop3</span> + user <span class="var"><username></span>@<span class="var"><domain></span> with password '<span class="var"><password></span>' is '<span class="var"><username></span>' here + <span class="security">ssl</span> +mda '/etc/maildelivery.sh %T' + +# Use the mda line below to disable filtering +#mda '/usr/bin/procmail -d %T' +</pre> + +<p class="filename">/etc/init.d/fetchmail</p> +<pre> +#!/bin/bash + +cut -d: -f1 /etc/passwd | while read USERNAME + do + if [ -f /home/${USERNAME}/.fetchmailrc ]; then + pid=`head -1 /home/${USERNAME}/.fetchmail.pid 2>/dev/null` + if [ "$1" = "start" ] && [ `kill -0 $pid 2>/dev/null; echo $?` -ne 0 ]; then + echo "Starting fetchmail for user: ${USERNAME}" + su - ${USERNAME} -c "fetchmail --daemon <span class="suggested">300</span> -f ~/.fetchmailrc" + elif [ "$1" = "stop" ]; then + echo "Stopping fetchmail for user: ${USERNAME}" + kill $pid + elif [ "$1" = "status" ]; then + if [ `kill -0 $pid 2>/dev/null; echo $?` -eq 0 ]; then + echo "Fetchmail is UP for user: ${USERNAME}" + else + echo "Fetchmail is DOWN for user: ${USERNAME}" + fi + fi + fi + done +</pre> + +<p class="filename">/etc/systemd/system/fetchmail.service</p> +<pre> +[Unit] +Description=Fetchmail multi-user mail import +After=local-fs.target network.target network-online.target + +[Service] +Type=oneshot +ExecStart=/etc/init.d/fetchmail start +ExecStop=/etc/init.d/fetchmail stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target +</pre> + +<p>Enable the Fetchmail service</p> +<pre> +systemctl enable fetchmail +</pre> + +<h1>Configure Dovecot</h1> + + +<p class="filename">/etc/dovecot/dovecot.conf</p> +<pre> +protocols = imap +listen = <span class="suggested">mail.</span><span class="var"><domain></span> +verbose_proctitle = <span class="suggested">yes</span> +shutdown_clients = <span class="suggested">yes</span> +</pre> + +<p class="filename">/etc/dovecot/conf.d/10-auth.conf</p> +<pre> +disable_plaintext_auth = <span class="security">yes</span> +auth_mechanism = <span class="suggested">plain cram-md5</span> +!include auth-passwdfile.conf.ext +</pre> + +<p class="filename">/etc/dovecot/conf.d/auth-passwdfile.conf.ext</p> +<pre> +passdb { + driver = passwd-file + args = scheme=cram-md5 <span class="suggested">/etc/dovecot/cram-md5.pwd</span> +} + +# userdb { ... } +</pre> + +<p>Get the cram-md5 password hash using emailrelay-passwd and create the password file:</p> +<pre> +emailrelay-passwd +touch <span class="suggested">/etc/dovecot/cram-md5.pwd</span> +chmod <span class="security">0600</span> <span class="suggested">/etc/dovecot/cram-md5.pwd</span> +chown dovecot /etc/dovecot/cram-md5.pwd +nano <span class="suggested">/etc/dovecot/cram-md5.pwd</span> +</pre> + +<p class="filename">/etc/dovecot/cram-md5.pwd</p> +<pre> +<span class="var"><username></span>:<span class="var"><cram-md5 formatted password></span> +</pre> + +<p class="filename">/etc/dovecot/conf.d/10-director.conf</p> +<pre> +<span class="todo">...</span> +</pre> + +<p class="filename">/etc/dovecot/conf.d/10-logging.conf</p> +<pre> +<span class="todo">...</span> +</pre> + +<p class="filename">/etc/dovecot/conf.d/10-mail.conf</p> +<pre> +mail_location = mbox:~/mail:INBOX=/var/mail/%u +mail_attachment_dir = ~/attachments +</pre> + +<p class="filename">/etc/dovecot/conf.d/10-master.conf</p> +<pre> +<span class="security"> +#inet_listener imap{<span class="todo">...</span>} +inet_listener imaps{<span class="todo">...</span>} +#service pop{<span class="todo">...</span>} +#service lmtp{<span class="todo">...</span>} +</span> +</pre> + +<p class="filename">/etc/dovecot/conf.d/10-ssl.conf</p> +<pre> +<span class="security"> +ssl = yes +ssl_cert = <<span class="suggested">/etc/pki/dovecot/certs/<span class="var">domain</span>.crt</span> +ssl_key = <<span class="suggested">/etc/pki/dovecot/private/<span class="var">domain</span>.key</span> +ssl_ca = <<span class="suggested">/etc/pki/dovecot/certs/<span class="var">ca</span>.pem</span> +</span> +</pre> + +<p class="filename">/etc/dovecot/conf.d/15-lda.conf</p> +<pre> +<span class="suggested"> +postmaster_address = mail@<span class="var"><domain></span> +hostname = mail.<span class="var"><domain></span> +</span> +</pre> + +<p class="filename">/etc/dovecot/conf.d/20-imap.conf</p> +<pre> +imap_idle_notify_interval = <span class="suggested">1 mins</span> +</pre> + +<p>Enable the Dovecot service</p> +<pre> +systemctl enable dovecot +</pre> + +<h1>Install E-mailrelay</h1> +<pre> +sudo yum install gcc gcc-c++ <span class="security">openssl openssl-devel</span> +cd ~ +wget https://sourceforge.net/projects/emailrelay/files/latest/download?source=files +mv emailrelay* emailrelay.tar.gz +tar -xzvf emailrelay.tar.gz +cd emailrelay* +./configure <span class="security">--with-openssl</span> +make +make install +</pre> + +<h1>Configure E-mailrelay</h1> +<p>Prepare SSL keys for E-mailrelay</p> +<pre> +<span class="security"> +cat <span class="suggested">/etc/pki/dovecot/certs/<span class="var">domain</span>.crt</span> <span class="suggested">/etc/pki/dovecot/private/<span class="var">domain</span>.key</span> > <span class="suggested">/etc/pki/dovecot/private/<span class="var">domain</span>.crt.key</span> +</span> +</pre> + +<p>Prepare authentication file</p> +<pre> +touch /etc/emailrelay.auth +chmod <span class="security">0600</span> /etc/emailrelay.auth +</pre> + +<p class="filename">/etc/emailrelay.auth</p> +<pre> +CRAM-MD5 server <span class="var"><E-mailrelay client login></span> <span class="var"><CRAM-MD5 encoded password></span> +PLAIN client <span class="var"><remote SMTP server login></span> <span class="var"><plaintext password></span> +</pre> + +<p>Create E-mailrelay filter for local mail delivery</p> +<p class="filename">/etc/emailrelay-filter.sh</pre> +<pre> +#!/bin/sh +# emailrelay-filter.sh + +# Function (if required) to convert incoming mail address to local username +# As designed, this function will take an address like 'alias-user@domain.com' +# and deliver it to 'user' +addrToUser() +{ + <span class="suggested">ADDR="${1}" + USER=`echo $ADDR | awk -F"-" '{print $NF}'` + echo "$USER"</span> +} + +content="${1}" +envelope="`echo \"${content}\" | sed 's/content/envelope.new/'`" +destination="`cat ${content} | grep '^To:' | cut -d':' -f2-`" + +while [ ! -z "${destination}" ]; do + islocal=`echo ${destination} | grep "@<span class="var">domain</span>" | wc -l` + if [ "$islocal" -lt 1 ]; then + exit 0 + else + user="`echo ${destination} | sed 's/\([^ <]*\)@<span class="var">domain</span>[^ ;]*/\1/'`" + destination="`echo ${destination} | sed \"s/${user}@<span class="var">domain</span>//\"`" + localuser=`addrToUser ${user}` + cat "${content}" | grep -v "^To:" | sudo /usr/bin/procmail -d ${localuser} + fi + sleep 5 +done + +rm ${content} ${envelope} +exit 100 +</pre> + +<p>Configure retry and failure notifications</p> +<pre> +<span class="todo"> +/usr/local/libexec/emailrelay/examples/emailrelay-notify.sh +/usr/local/libexec/emailrelay/examples/emailrelay-resubmit.sh +</span> +</pre> + +<p>Create init file for E-mailrelay</p> +<pre> +touch /etc/init.d/emailrelay +chmod +x /etc/init.d/emailrelay +</pre> +<p class="filename">/etc/init.d/emailrelay</p> +<pre> +#!/bin/bash + +#. /etc/init.d/functions + +if [ "$1" = "start" ]; then + /usr/local/sbin/emailrelay --as-proxy <span class="var">remote SMTP server</span>:<span class="security">587</span> <span class="security">--client-tls \ + --client-auth /etc/emailrelay.auth</span> <span class="suggested">--port 10025</span> -r <span class="security">--server-tls <span class="suggested">/etc/pki/dovecot/private/<span class="var">domain</span>.crt.key</span></span> \ + <span class="suggested">--filter /etc/emailrelay-filter.sh --pid-file /etc/emailrelay.pid</span> <span class="suggested">--verbose > /var/log/emailrelay.log</span> +elif [ "$1" = "stop" ]; then + kill `cat /etc/emailrelay.pid` +elif [ "$1" = "status" ]; then + pid=`cat /etc/emailrelay.pid` + wc=`ps -p $pid | wc -l` + if [ ! -z "$pid" ] && [ $wc -gt 1 ]; then + echo "E-mailrelay is running" + else + echo "E-mailrelay is NOT running" + fi +fi +</pre> + +<p class="filename">/etc/systemd/system/emailrelay.service</p> +<pre> +[Unit] +Description=Emailrelay smtp proxy +After=local-fs.target network.target network-online.target + +[Service] +Type=simple +PIDFile=/etc/emailrelay.pid +ExecStart=/usr/local/sbin/emailrelay --as-proxy <span class="var">remote SMTP server</span>:<span class="security">587</span> <span class="security">--client-tls \ + --client-auth /etc/emailrelay.auth</span> <span class="suggested">--port 10025</span> -r <span class="security">--server-tls <span class="suggested">/etc/pki/dovecot/private/<span class="var">domain</span>.crt.key</span></span> \ + <span class="security">--server-auth=/etc/emailrelay.auth</span> + <span class="suggested">--filter /etc/emailrelay-filter.sh --pid-file /etc/emailrelay.pid</span> <span class="suggested">--verbose > /var/log/emailrelay.log</span> +ExecStop=kill `cat /etc/emailrelay.pid` + +[Install] +WantedBy=multi-user.target +</pre> + +<p>Enable the Emailrelay service</p> +<pre> +systemctl enable emailrelay +</pre> + +<h1>Configure sudo access</h1> +<pre class="filename">/etc/sudoers</pre> +<pre> +# Allow sudo to be used in fetchmail mda script +#Defaults requiretty + +# Allow users to send mail to other users +daemon mail.bsflowers.net = (root) NOPASSWD: /usr/bin/procmail +%mail mail.bsflowers.net = (root) NOPASSWD: /usr/bin/procmail +</pre> + +<h1>Reboot and confirm services</h1> +<pre> +reboot +systemctl status dovecot +systemctl status emailrelay +systemctl status fetchmail +</pre> + +<h1>Verification</h1> +<p>The following optional steps will help verify or troubleshoot the installation</p> + +<h2>Check Dovecot Status</h2> +<p>This will show if the Dovecot server is running</p> +<pre> +systemctl status dovecot +</pre> + +<h2>Check Dovecot Logs</h2> +<p>Check for errors, and watch these logs while performing remaining steps</p> +<pre> +tail -f /var/log/dovecot.log +</pre> + +<h2>Login to dovecot with SSL</h2> +<p>The following commands are to login to the Dovecot IMAP server via SSL on port 993, +and open the user's inbox. </p> +<pre> +openssl s_client -crlf -connect mail.<span class="var"><domain></span>:993 +tag login <span class="var"><username></span> "<span class="var"><password></span>" +tag LIST "" "*" +tag SELECT INBOX +</pre> +<p>You can also use this to check the certificate expiration dates</p> +<pre> +openssl s_client -crlf -connect mail.openssl s_client -crlf -connect mail.<span class="var"><domain></span>:993 | openssl x509 -noout -dates +</pre> + +<h2>Check E-mailrelay logs</h2> +<pre> +tail -f /var/log/maillog +</pre> + +<h2>Check user's mailbox locally</h2> +<pre> +su - <span class="var">user</span> mail +</pre> + +</body> +</html> diff --git a/centos_httpd.html b/centos_httpd.html new file mode 100644 index 0000000..a857aaf --- /dev/null +++ b/centos_httpd.html @@ -0,0 +1,111 @@ +<html> + <head> + <title>Apache on Centos 7</title> + <script src="/scripts/charNames.js" ></script> + <link rel="icon" type="image/png" href="/favicon.png"> + <meta name="title" content="Apache on Centos 6"> + <meta name="description" content="Installing and configuring Apache + web server on a Centos 7 VM."> + <style> + pre + { + background-color: #DDD; + padding: .5em .75em; + margin: 0em; + font-weight: 600; + } + + .filename + { + margin-bottom: 0em; + padding-bottom: 0em; + background-color:#CCCCCC; + font-weight: bold; + padding: .2em .5em; + font-size: 1.1em; + } + + .filename:before + { + content: "nano "; + } + + .TODO + { + background-color: #DD5; + font-weight: bold; + } + + .var + { + color: #383; + font-weight: bold; + } + + .suggested + { + color: #AA0; + font-weight: bold; + } + + .security + { + color: #C44; + font-weight: bold; + } + </style> + </head> + +<body> + +<h1>Legend</h1> +<p> +<span class="todo">Work in progress</span><br> +<span class="var">Installation specific values</span><br> +<span class="suggested">SC standard configuration</span><br> +<span class="security">Security configuration</span> +</p> + +<h1>Base System Setup</h1> +<p>Update the OS and install httpd, ssh, and nano</p> +<pre> +yum update +yum install sudo nano openssh-server mod_ssl openssl httpd +</pre> + +<p>Install any optional plugins. For example, PHP</p> +<pre> +<span class="suggested">yum install php</span> +</pre> + +<h1>Configure the server</h1> +<p class="filename">/etc/httpd/conf/httpd.conf</p> +<pre> +<span class="security">#Listen 80</span> +<span class="suggested">ServerAdmin www@<span class="var">domain</span></span> +</pre> + +<h1>Configure SSL</h1> +<p>If this server is hosting multiple domains, move the entire virtualhost tag into a separate file + (/etc/httpd/conf.d/<span class="var">domain</span>.conf) and create copies of that file for each domain +<br/>And update certificate filenames as required (these are based on letsencrypt.org certs).</p> +<p class="filename">/etc/httpd/conf.d/ssl.conf</p> +<pre> +<VirtualHost <span class="var">domain</span>:443> +DocumentRoot "/var/www/html/<span class="var">domain</span> +ServerAdmin www@<span class="var">domain</span> +SSLCertificateFile /etc/pki/tls/certs/<span class="var">domain</span>/cert.pem +SSLCertificateKeyFile /etc/pki/tls/certs/<span class="var">domain</span>/privkey.pem +SSLCertificateChainFile /etc/pki/tls/certs/<span class="var">domain</span>/chain.pem +</VirtualHost> +</pre> + +<h1>Start the server</h1> +<pre> +systemctl enable httpd +systemctl start httpd +systemctl enable sshd +systemctl start sshd +</pre> +</body> +</html> diff --git a/debian_git.html b/debian_git.html new file mode 100644 index 0000000..dd4e54f --- /dev/null +++ b/debian_git.html @@ -0,0 +1,122 @@ +<html> + <head> + <title>Git server on Debian 8</title> + <script src="/scripts/charNames.js" ></script> + <link rel="icon" type="image/png" href="/favicon.png"> + <meta name="title" content="Git server on Debian 8"> + <meta name="description" content="Installing and configuring a Git + repo and gitweb server on a Debian 8 VM."> + <style> + pre + { + background-color: #DDD; + padding: .5em .75em; + margin: 0em; + font-weight: 600; + } + + .filename + { + margin-bottom: 0em; + padding-bottom: 0em; + background-color:#CCCCCC; + font-weight: bold; + padding: .2em .5em; + font-size: 1.1em; + } + + .filename:before + { + content: "nano "; + } + + .TODO + { + background-color: #DD5; + font-weight: bold; + } + + .var + { + color: #383; + font-weight: bold; + } + + .suggested + { + color: #AA0; + font-weight: bold; + } + + .security + { + color: #C44; + font-weight: bold; + } + </style> + </head> + +<body> + +<h1>Legend</h1> +<p> +<span class="todo">Work in progress</span><br> +<span class="var">Installation specific values</span><br> +<span class="suggested">SC standard configuration</span><br> +<span class="security">Security configuration</span> +</p> + +<h1>Base System Setup</h1> +<p>Update the OS and install the git server</p> +<pre> +apt-get update +apt-get upgrade +apt-get install git-core gitweb +</pre> + +<h1>Configure Git server</h1> +<p class="filename">/etc/gitweb.conf</p> +<pre> +$projectroot = "/home/git"; +</pre> + +<pre> +useradd git -m -d /home/git -s /bin/bash +su - git +git config --global user.name "<span class="var">Repo Owner's Name</span>" +git config --global user.email git@<span class="var">domain</span> +</pre> +<h1>Add a project</h1> +<pre> +mkdir <span class="var">project1</span>.git +cd <span class="var">project1</span> +git init --bare +service apache2 restart +</pre> + +<h1>Configure Apache webserver</h1> +<p class="filename">/etc/apache2/ports.conf</p> +<pre> +#Listen 80 +</pre> + +<p class="filename">/etc/apache2/sites-available/default-ssl.conf</p> +<pre> +ServerAdmin git@<span class="var">domain</span> +DocumentRoot /usr/share/gitweb + +SSLCertificateFile /etc/ssl/certs/<span class="var">domain</span>/cert.pem +SSLCertificateKeyFile /etc/ssl/certs/<span class="var">domain</span>/privkey.pem +SSLCertificateChainFile /etc/ssl/certs/<span class="var">domain</span>/fullchain.pem +</pre> + +<pre> +rn /etc/apache2/sites-enabled/000-default.conf +ln /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-enabled/default-ssl.conf +a2enmod cgi +a2enmod ssl +service apache2 restart +</pre> + +</body> +</html> diff --git a/servers/centos_dovecot.html b/servers/centos_dovecot.html new file mode 100755 index 0000000..1efc699 --- /dev/null +++ b/servers/centos_dovecot.html @@ -0,0 +1,579 @@ +<html> + <head> + <title>Dovecot on Centos 7</title> + <script src="/scripts/charNames.js" ></script> + <link rel="icon" type="image/png" href="/favicon.png"> + <meta name="title" content="Dovecot on Centos 6"> + <meta name="description" content="Installing and configuring Dovecot and + E-mailrelay as an intermediate mail server on a Centos 6 VM."> + <style> + pre + { + background-color: #DDD; + padding: .5em .75em; + margin: 0em; + font-weight: 600; + } + + .filename + { + margin-bottom: 0em; + padding-bottom: 0em; + background-color:#CCCCCC; + font-weight: bold; + padding: .2em .5em; + font-size: 1.1em; + } + + .filename:before + { + content: "nano "; + } + + .TODO + { + background-color: #DD5; + font-weight: bold; + } + + .var + { + color: #383; + font-weight: bold; + } + + .suggested + { + color: #AA0; + font-weight: bold; + } + + .security + { + color: #C44; + font-weight: bold; + } + </style> + </head> + +<body> + +<h1>Legend</h1> +<p> +<span class="todo">Work in progress</span><br> +<span class="var">Installation specific values</span><br> +<span class="suggested">SC standard configuration</span><br> +<span class="security">Security configuration</span> +</p> + +<h1>Base System Setup</h1> +<p>Update the OS and install dovecot and (optionally) nano</p> +<pre> +yum update +yum install sudo nano wget mailx dovecot procmail fetchmail +</pre> + +<p>Create required user accounts.</p> +<p>For the fetchmail filtering described in the + next step, you may also want to create the users <span class="suggested"> + spam</span> and <span class="suggested">pending</span></p> +<pre> +useradd <span class="var"><username></span> -m -d /home/<span class="var"><username></span> -s /bin/bash +usermod -a -G mail <span class="var"><username></span> +su - <span class="var"><username></span> +</pre> + +<h1>Configure Fetchmail</h1> +<p>Create required files:</p> +<pre> +touch /home/<span class="var"><username></span>/.fetchmailrc +chmod 0600 /home/<span class="var"><username></span>/.fetchmailrc +touch /etc/init.d/fetchmail +chmod +x /etc/init.d/fetchmail +</pre> + +<p>Create mail filter (if desired).</p> +<p>The filter shown below has a number of different features. Each block can be removed if + not required. Read the script comments for details.</p> +<p>The first block is spam filtering by address -- any messages sent to an address listed + in the file /etc/mailblock.lst (one address per line) will be filtered and delivered to + the 'spam' user. You should have a 'spam' user setup the same as your other mail + accounts to use this feature.</p> +<p>The second block is two-step verification filtering -- any messages sent to an address + listed in the file /etc/mailverify.lst will be held for verification. To use this feature, + you must configure a user 'pending' as well as a wildcard alias on '*-pending'. When a + message is delivered for one of the designated addresses, it will be stored with a randomly + generated ID number and a message will be sent to the sender from the address '<random>-pending'. + When the user replies to that mail, their original message will be sent to the address + originally provided</p> +<p class="filename">/etc/mailDelivery.sh</pre> +<pre> +# The destination user can be selected either by an argument to the script, +# or based on the user who is executing the script +user="${1}" +if [ -z "${user}" ]; then + user=`whoami` +fi + +# Read the message and filter the destination addresses from it +# The addresses will have "^" and "$" characters added to the start and end +# for later grep commands. +message=$(cat; echo x) +address="`echo -n \"${message%x}\" | \ + grep -e '^To: ' -e \$'^[ \t]*for' | \ + awk '{print \"^\"$2\"\$\"}' | \ + sed 's/[\"<>;]//g'`" + + + + +# If a blacklist is provided at /etc/mailblock.lst, messages sent to that address +# will be redirected to the inbox of the "spam" user +if [ `cat /etc/mailblock.lst | grep -ic "${address}"` -gt 0 ]; then + user="spam" + + + +# If a list is provided at /etc/mailverify.lst, messages sent to those address +# will require additional verification before being delivered. +# A mail account must be configured for the 'pending' user, with a wildcard alias +# configured on *-pending@<span class="var">domain</span> +elif [ `cat /etc/mailverify.lst | grep -ic "${address}"` -gt 0 ]; then + # First, generate a random ID number to identify this message + idnum=$((RANDOM)) + attempts=0 + if [ ! -d /home/pending/messages/ ]; then + mkdir -p /home/pending/messages/ + fi + + # If the number is already used, retry up to ten times + while [ -f /home/pending/messages/$idnum.msg ] && [ $attempts -lt 10 ]; do + idnum=$((RANDOM)) + attempts=`expr $attempts + 1` + done + + # If we could not find a free number, fail to deliver + # The user will be sent the contents of /home/pending/failure.msg + # and their original message + if [ $attempts -eq 10 ]; then + echo "FAILURE" + msg=$(cat /home/pending/failure.msg) + echo "${msg} ${message}" | mailx -v \ + -s "Your message could not be delivered" \ + -S smtp-auth=cram-md5 \ + -S smtp=smtp://mail.<span class="var">domain</span>:10025 \ + -S from="<span class="var">domain</span> pending messages <$idnum-pending@<span class="var">domain</span>>" \ + -S smtp-auth-user=pending \ + -S smtp-auth-password='<span class="var">password</span>' \ + -S nss-config-dir="/etc/pki/nssdb/" \ + -S ssl-verify=warn \ + -S smtp-use-starttls \ + "${from}" + exit 1 + fi + + # Save the message, and give all mail users permission to access it + # This is required so it can be accessed by the correct destination user + echo -n "${message%x}" > /home/pending/messages/$idnum + chown `whoami`:mail /home/pending/messages/$idnum + chmod 660 /home/pending/messages/$idnum + + # Get the sender's address from the message, and send them the contents of + # /home/pending/autoresponse.msg, with their message attached. The message + # will be sent from the address <random number>-pending@<span class="var">domain</span> + # and will be released when a reply is received to the same address + from="`cat /home/pending/messages/$idnum | \ + grep '^From:' | \ + cut -d':' -f2- | \ + sed 's/[^@]*[ <]\([^ ]*@[^ ]*\)[^@]*/\1/g' | \ + sed 's/[\"<>;]//g'`" + cat /home/pending/autoresponse.msg | mailx -v \ + -a /home/pending/messages/$idnum \ + -s "Action required: Your message was not delivered" \ + -S smtp-auth=cram-md5 \ + -S smtp=smtp://mail.<span class="var">domain</span>:10025 \ + -S from="<span class="var">domain</span> pending messages >$idnum-pending@<span class="var">domain</span>>" \ + -S smtp-auth-user=pending \ + -S smtp-auth-password='<span class="var">password</span>' \ + -S nss-config-dir="/etc/pki/nssdb/" \ + -S ssl-verify=warn \ + -S smtp-use-starttls \ + "${from}" + exit 0 + +# If a reply is received to a *-pending@<span class="var">domain</span> address, +# send the saved message instead +elif [ `ls /home/pending/messages/ | sed 's/$/-pending@bsflowers.net/g' | grep -ic "${address}"` -gt 0 ]; then + idnum="`echo \"${address}\" | \ + sed 's/\^\([0-9]*\)-pending.*/\1/' | \ + sort -u | \ + grep -v [^0-9]`" + destination="`cat /home/pending/messages/$idnum | \ + grep -e '^To: ' -e \$'^[ \t]*for' | \ + awk '{print \"^\"$2\"\$\"}' | \ + sed 's/[\"<>;]//g'`" + + user=`echo $destination | cut -d '@' -f1 | cut -d'-' -f2 | sed 's/^^//g'` + cat /home/pending/messages/$idnum | sudo /usr/bin/procmail -d $user + rm /home/pending/messages/$idnum + exit 0 +fi + + + +# Useful for debugging -- saves a copy of each message in the user home +# echo -n "${message%x}" > /home/$user/mail.tmp + +# Send the message +echo -n "${message%x}" | sudo /usr/bin/procmail -d $user +</pre> + +<p class="filename">/etc/mailblock.lst</p> +<pre> +spammy-address@<span class="var">domain</span> +</pre> + +<p class="filename">/home/<span class="var"><username></span>/.fetchmailrc</p> +<pre> +set daemon <span class="suggested">300</span> +poll <span class="var"><external mailserver></span> with proto <span class="suggested">pop3</span> + user <span class="var"><username></span>@<span class="var"><domain></span> with password '<span class="var"><password></span>' is '<span class="var"><username></span>' here + <span class="security">ssl</span> +mda '/etc/maildelivery.sh %T' + +# Use the mda line below to disable filtering +#mda '/usr/bin/procmail -d %T' +</pre> + +<p class="filename">/etc/init.d/fetchmail</p> +<pre> +#!/bin/bash + +cut -d: -f1 /etc/passwd | while read USERNAME + do + if [ -f /home/${USERNAME}/.fetchmailrc ]; then + pid=`head -1 /home/${USERNAME}/.fetchmail.pid 2>/dev/null` + if [ "$1" = "start" ] && [ `kill -0 $pid 2>/dev/null; echo $?` -ne 0 ]; then + echo "Starting fetchmail for user: ${USERNAME}" + su - ${USERNAME} -c "fetchmail --daemon <span class="suggested">300</span> -f ~/.fetchmailrc" + elif [ "$1" = "stop" ]; then + echo "Stopping fetchmail for user: ${USERNAME}" + kill $pid + elif [ "$1" = "status" ]; then + if [ `kill -0 $pid 2>/dev/null; echo $?` -eq 0 ]; then + echo "Fetchmail is UP for user: ${USERNAME}" + else + echo "Fetchmail is DOWN for user: ${USERNAME}" + fi + fi + fi + done +</pre> + +<p class="filename">/etc/systemd/system/fetchmail.service</p> +<pre> +[Unit] +Description=Fetchmail multi-user mail import +After=local-fs.target network.target network-online.target + +[Service] +Type=oneshot +ExecStart=/etc/init.d/fetchmail start +ExecStop=/etc/init.d/fetchmail stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target +</pre> + +<p>Enable the Fetchmail service</p> +<pre> +systemctl enable fetchmail +</pre> + +<h1>Configure Dovecot</h1> + + +<p class="filename">/etc/dovecot/dovecot.conf</p> +<pre> +protocols = imap +listen = <span class="suggested">mail.</span><span class="var"><domain></span> +verbose_proctitle = <span class="suggested">yes</span> +shutdown_clients = <span class="suggested">yes</span> +</pre> + +<p class="filename">/etc/dovecot/conf.d/10-auth.conf</p> +<pre> +disable_plaintext_auth = <span class="security">yes</span> +auth_mechanism = <span class="suggested">plain cram-md5</span> +!include auth-passwdfile.conf.ext +</pre> + +<p class="filename">/etc/dovecot/conf.d/auth-passwdfile.conf.ext</p> +<pre> +passdb { + driver = passwd-file + args = scheme=cram-md5 <span class="suggested">/etc/dovecot/cram-md5.pwd</span> +} + +# userdb { ... } +</pre> + +<p>Get the cram-md5 password hash using emailrelay-passwd and create the password file:</p> +<pre> +emailrelay-passwd +touch <span class="suggested">/etc/dovecot/cram-md5.pwd</span> +chmod <span class="security">0600</span> <span class="suggested">/etc/dovecot/cram-md5.pwd</span> +chown dovecot /etc/dovecot/cram-md5.pwd +nano <span class="suggested">/etc/dovecot/cram-md5.pwd</span> +</pre> + +<p class="filename">/etc/dovecot/cram-md5.pwd</p> +<pre> +<span class="var"><username></span>:<span class="var"><cram-md5 formatted password></span> +</pre> + +<p class="filename">/etc/dovecot/conf.d/10-director.conf</p> +<pre> +<span class="todo">...</span> +</pre> + +<p class="filename">/etc/dovecot/conf.d/10-logging.conf</p> +<pre> +<span class="todo">...</span> +</pre> + +<p class="filename">/etc/dovecot/conf.d/10-mail.conf</p> +<pre> +mail_location = mbox:~/mail:INBOX=/var/mail/%u +mail_attachment_dir = ~/attachments +</pre> + +<p class="filename">/etc/dovecot/conf.d/10-master.conf</p> +<pre> +<span class="security"> +#inet_listener imap{<span class="todo">...</span>} +inet_listener imaps{<span class="todo">...</span>} +#service pop{<span class="todo">...</span>} +#service lmtp{<span class="todo">...</span>} +</span> +</pre> + +<p class="filename">/etc/dovecot/conf.d/10-ssl.conf</p> +<pre> +<span class="security"> +ssl = yes +ssl_cert = <<span class="suggested">/etc/pki/dovecot/certs/<span class="var">domain</span>.crt</span> +ssl_key = <<span class="suggested">/etc/pki/dovecot/private/<span class="var">domain</span>.key</span> +ssl_ca = <<span class="suggested">/etc/pki/dovecot/certs/<span class="var">ca</span>.pem</span> +</span> +</pre> + +<p class="filename">/etc/dovecot/conf.d/15-lda.conf</p> +<pre> +<span class="suggested"> +postmaster_address = mail@<span class="var"><domain></span> +hostname = mail.<span class="var"><domain></span> +</span> +</pre> + +<p class="filename">/etc/dovecot/conf.d/20-imap.conf</p> +<pre> +imap_idle_notify_interval = <span class="suggested">1 mins</span> +</pre> + +<p>Enable the Dovecot service</p> +<pre> +systemctl enable dovecot +</pre> + +<h1>Install E-mailrelay</h1> +<pre> +sudo yum install gcc gcc-c++ <span class="security">openssl openssl-devel</span> +cd ~ +wget https://sourceforge.net/projects/emailrelay/files/latest/download?source=files +mv emailrelay* emailrelay.tar.gz +tar -xzvf emailrelay.tar.gz +cd emailrelay* +./configure <span class="security">--with-openssl</span> +make +make install +</pre> + +<h1>Configure E-mailrelay</h1> +<p>Prepare SSL keys for E-mailrelay</p> +<pre> +<span class="security"> +cat <span class="suggested">/etc/pki/dovecot/certs/<span class="var">domain</span>.crt</span> <span class="suggested">/etc/pki/dovecot/private/<span class="var">domain</span>.key</span> > <span class="suggested">/etc/pki/dovecot/private/<span class="var">domain</span>.crt.key</span> +</span> +</pre> + +<p>Prepare authentication file</p> +<pre> +touch /etc/emailrelay.auth +chmod <span class="security">0600</span> /etc/emailrelay.auth +</pre> + +<p class="filename">/etc/emailrelay.auth</p> +<pre> +CRAM-MD5 server <span class="var"><E-mailrelay client login></span> <span class="var"><CRAM-MD5 encoded password></span> +PLAIN client <span class="var"><remote SMTP server login></span> <span class="var"><plaintext password></span> +</pre> + +<p>Create E-mailrelay filter for local mail delivery</p> +<p class="filename">/etc/emailrelay-filter.sh</pre> +<pre> +#!/bin/sh +# emailrelay-filter.sh + +# Function (if required) to convert incoming mail address to local username +# As designed, this function will take an address like 'alias-user@domain.com' +# and deliver it to 'user' +addrToUser() +{ + <span class="suggested">ADDR="${1}" + USER=`echo $ADDR | awk -F"-" '{print $NF}'` + echo "$USER"</span> +} + +content="${1}" +envelope="`echo \"${content}\" | sed 's/content/envelope.new/'`" +destination="`cat ${content} | grep '^To:' | cut -d':' -f2-`" + +while [ ! -z "${destination}" ]; do + islocal=`echo ${destination} | grep "@<span class="var">domain</span>" | wc -l` + if [ "$islocal" -lt 1 ]; then + exit 0 + else + user="`echo ${destination} | sed 's/\([^ <]*\)@<span class="var">domain</span>[^ ;]*/\1/'`" + destination="`echo ${destination} | sed \"s/${user}@<span class="var">domain</span>//\"`" + localuser=`addrToUser ${user}` + cat "${content}" | grep -v "^To:" | sudo /usr/bin/procmail -d ${localuser} + fi + sleep 5 +done + +rm ${content} ${envelope} +exit 100 +</pre> + +<p>Configure retry and failure notifications</p> +<pre> +<span class="todo"> +/usr/local/libexec/emailrelay/examples/emailrelay-notify.sh +/usr/local/libexec/emailrelay/examples/emailrelay-resubmit.sh +</span> +</pre> + +<p>Create init file for E-mailrelay</p> +<pre> +touch /etc/init.d/emailrelay +chmod +x /etc/init.d/emailrelay +</pre> +<p class="filename">/etc/init.d/emailrelay</p> +<pre> +#!/bin/bash + +#. /etc/init.d/functions + +if [ "$1" = "start" ]; then + /usr/local/sbin/emailrelay --as-proxy <span class="var">remote SMTP server</span>:<span class="security">587</span> <span class="security">--client-tls \ + --client-auth /etc/emailrelay.auth</span> <span class="suggested">--port 10025</span> -r <span class="security">--server-tls <span class="suggested">/etc/pki/dovecot/private/<span class="var">domain</span>.crt.key</span></span> \ + <span class="suggested">--filter /etc/emailrelay-filter.sh --pid-file /etc/emailrelay.pid</span> <span class="suggested">--verbose > /var/log/emailrelay.log</span> +elif [ "$1" = "stop" ]; then + kill `cat /etc/emailrelay.pid` +elif [ "$1" = "status" ]; then + pid=`cat /etc/emailrelay.pid` + wc=`ps -p $pid | wc -l` + if [ ! -z "$pid" ] && [ $wc -gt 1 ]; then + echo "E-mailrelay is running" + else + echo "E-mailrelay is NOT running" + fi +fi +</pre> + +<p class="filename">/etc/systemd/system/emailrelay.service</p> +<pre> +[Unit] +Description=Emailrelay smtp proxy +After=local-fs.target network.target network-online.target + +[Service] +Type=simple +PIDFile=/etc/emailrelay.pid +ExecStart=/usr/local/sbin/emailrelay --as-proxy <span class="var">remote SMTP server</span>:<span class="security">587</span> <span class="security">--client-tls \ + --client-auth /etc/emailrelay.auth</span> <span class="suggested">--port 10025</span> -r <span class="security">--server-tls <span class="suggested">/etc/pki/dovecot/private/<span class="var">domain</span>.crt.key</span></span> \ + <span class="security">--server-auth=/etc/emailrelay.auth</span> + <span class="suggested">--filter /etc/emailrelay-filter.sh --pid-file /etc/emailrelay.pid</span> <span class="suggested">--verbose > /var/log/emailrelay.log</span> +ExecStop=kill `cat /etc/emailrelay.pid` + +[Install] +WantedBy=multi-user.target +</pre> + +<p>Enable the Emailrelay service</p> +<pre> +systemctl enable emailrelay +</pre> + +<h1>Configure sudo access</h1> +<pre class="filename">/etc/sudoers</pre> +<pre> +# Allow sudo to be used in fetchmail mda script +#Defaults requiretty + +# Allow users to send mail to other users +daemon mail.bsflowers.net = (root) NOPASSWD: /usr/bin/procmail +%mail mail.bsflowers.net = (root) NOPASSWD: /usr/bin/procmail +</pre> + +<h1>Reboot and confirm services</h1> +<pre> +reboot +systemctl status dovecot +systemctl status emailrelay +systemctl status fetchmail +</pre> + +<h1>Verification</h1> +<p>The following optional steps will help verify or troubleshoot the installation</p> + +<h2>Check Dovecot Status</h2> +<p>This will show if the Dovecot server is running</p> +<pre> +systemctl status dovecot +</pre> + +<h2>Check Dovecot Logs</h2> +<p>Check for errors, and watch these logs while performing remaining steps</p> +<pre> +tail -f /var/log/dovecot.log +</pre> + +<h2>Login to dovecot with SSL</h2> +<p>The following commands are to login to the Dovecot IMAP server via SSL on port 993, +and open the user's inbox. </p> +<pre> +openssl s_client -crlf -connect mail.<span class="var"><domain></span>:993 +tag login <span class="var"><username></span> "<span class="var"><password></span>" +tag LIST "" "*" +tag SELECT INBOX +</pre> +<p>You can also use this to check the certificate expiration dates</p> +<pre> +openssl s_client -crlf -connect mail.openssl s_client -crlf -connect mail.<span class="var"><domain></span>:993 | openssl x509 -noout -dates +</pre> + +<h2>Check E-mailrelay logs</h2> +<pre> +tail -f /var/log/maillog +</pre> + +<h2>Check user's mailbox locally</h2> +<pre> +su - <span class="var">user</span> mail +</pre> + +</body> +</html> diff --git a/servers/centos_httpd.html b/servers/centos_httpd.html new file mode 100644 index 0000000..a857aaf --- /dev/null +++ b/servers/centos_httpd.html @@ -0,0 +1,111 @@ +<html> + <head> + <title>Apache on Centos 7</title> + <script src="/scripts/charNames.js" ></script> + <link rel="icon" type="image/png" href="/favicon.png"> + <meta name="title" content="Apache on Centos 6"> + <meta name="description" content="Installing and configuring Apache + web server on a Centos 7 VM."> + <style> + pre + { + background-color: #DDD; + padding: .5em .75em; + margin: 0em; + font-weight: 600; + } + + .filename + { + margin-bottom: 0em; + padding-bottom: 0em; + background-color:#CCCCCC; + font-weight: bold; + padding: .2em .5em; + font-size: 1.1em; + } + + .filename:before + { + content: "nano "; + } + + .TODO + { + background-color: #DD5; + font-weight: bold; + } + + .var + { + color: #383; + font-weight: bold; + } + + .suggested + { + color: #AA0; + font-weight: bold; + } + + .security + { + color: #C44; + font-weight: bold; + } + </style> + </head> + +<body> + +<h1>Legend</h1> +<p> +<span class="todo">Work in progress</span><br> +<span class="var">Installation specific values</span><br> +<span class="suggested">SC standard configuration</span><br> +<span class="security">Security configuration</span> +</p> + +<h1>Base System Setup</h1> +<p>Update the OS and install httpd, ssh, and nano</p> +<pre> +yum update +yum install sudo nano openssh-server mod_ssl openssl httpd +</pre> + +<p>Install any optional plugins. For example, PHP</p> +<pre> +<span class="suggested">yum install php</span> +</pre> + +<h1>Configure the server</h1> +<p class="filename">/etc/httpd/conf/httpd.conf</p> +<pre> +<span class="security">#Listen 80</span> +<span class="suggested">ServerAdmin www@<span class="var">domain</span></span> +</pre> + +<h1>Configure SSL</h1> +<p>If this server is hosting multiple domains, move the entire virtualhost tag into a separate file + (/etc/httpd/conf.d/<span class="var">domain</span>.conf) and create copies of that file for each domain +<br/>And update certificate filenames as required (these are based on letsencrypt.org certs).</p> +<p class="filename">/etc/httpd/conf.d/ssl.conf</p> +<pre> +<VirtualHost <span class="var">domain</span>:443> +DocumentRoot "/var/www/html/<span class="var">domain</span> +ServerAdmin www@<span class="var">domain</span> +SSLCertificateFile /etc/pki/tls/certs/<span class="var">domain</span>/cert.pem +SSLCertificateKeyFile /etc/pki/tls/certs/<span class="var">domain</span>/privkey.pem +SSLCertificateChainFile /etc/pki/tls/certs/<span class="var">domain</span>/chain.pem +</VirtualHost> +</pre> + +<h1>Start the server</h1> +<pre> +systemctl enable httpd +systemctl start httpd +systemctl enable sshd +systemctl start sshd +</pre> +</body> +</html> diff --git a/servers/debian_git.html b/servers/debian_git.html new file mode 100644 index 0000000..dd4e54f --- /dev/null +++ b/servers/debian_git.html @@ -0,0 +1,122 @@ +<html> + <head> + <title>Git server on Debian 8</title> + <script src="/scripts/charNames.js" ></script> + <link rel="icon" type="image/png" href="/favicon.png"> + <meta name="title" content="Git server on Debian 8"> + <meta name="description" content="Installing and configuring a Git + repo and gitweb server on a Debian 8 VM."> + <style> + pre + { + background-color: #DDD; + padding: .5em .75em; + margin: 0em; + font-weight: 600; + } + + .filename + { + margin-bottom: 0em; + padding-bottom: 0em; + background-color:#CCCCCC; + font-weight: bold; + padding: .2em .5em; + font-size: 1.1em; + } + + .filename:before + { + content: "nano "; + } + + .TODO + { + background-color: #DD5; + font-weight: bold; + } + + .var + { + color: #383; + font-weight: bold; + } + + .suggested + { + color: #AA0; + font-weight: bold; + } + + .security + { + color: #C44; + font-weight: bold; + } + </style> + </head> + +<body> + +<h1>Legend</h1> +<p> +<span class="todo">Work in progress</span><br> +<span class="var">Installation specific values</span><br> +<span class="suggested">SC standard configuration</span><br> +<span class="security">Security configuration</span> +</p> + +<h1>Base System Setup</h1> +<p>Update the OS and install the git server</p> +<pre> +apt-get update +apt-get upgrade +apt-get install git-core gitweb +</pre> + +<h1>Configure Git server</h1> +<p class="filename">/etc/gitweb.conf</p> +<pre> +$projectroot = "/home/git"; +</pre> + +<pre> +useradd git -m -d /home/git -s /bin/bash +su - git +git config --global user.name "<span class="var">Repo Owner's Name</span>" +git config --global user.email git@<span class="var">domain</span> +</pre> +<h1>Add a project</h1> +<pre> +mkdir <span class="var">project1</span>.git +cd <span class="var">project1</span> +git init --bare +service apache2 restart +</pre> + +<h1>Configure Apache webserver</h1> +<p class="filename">/etc/apache2/ports.conf</p> +<pre> +#Listen 80 +</pre> + +<p class="filename">/etc/apache2/sites-available/default-ssl.conf</p> +<pre> +ServerAdmin git@<span class="var">domain</span> +DocumentRoot /usr/share/gitweb + +SSLCertificateFile /etc/ssl/certs/<span class="var">domain</span>/cert.pem +SSLCertificateKeyFile /etc/ssl/certs/<span class="var">domain</span>/privkey.pem +SSLCertificateChainFile /etc/ssl/certs/<span class="var">domain</span>/fullchain.pem +</pre> + +<pre> +rn /etc/apache2/sites-enabled/000-default.conf +ln /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-enabled/default-ssl.conf +a2enmod cgi +a2enmod ssl +service apache2 restart +</pre> + +</body> +</html> diff --git a/servers/description b/servers/description new file mode 100644 index 0000000..2d28bb5 --- /dev/null +++ b/servers/description @@ -0,0 +1 @@ +(Somewhat dated) tutorials for setup of some of the server software that I use diff --git a/webdesktop-source/01_setup.html b/webdesktop-source/01_setup.html new file mode 100755 index 0000000..e446183 --- /dev/null +++ b/webdesktop-source/01_setup.html @@ -0,0 +1,304 @@ +<html> + <head> + <title>Initial Setup</title> + <link rel="icon" type="image/png" href="/favicon.png"> + <meta name="title" content="Initial Setup"> + <meta name="description" content="This tutorial will guide + you through configuring a cloud-based Linux desktop accessible + from any device with a web browser and HTML5 support."> + <style> + pre + { + background-color: #CCC; + padding: .3em; + margin: .2em; + } + </style> + </head> + +<body> +<h1>Initial Setup</h1> + +<p>This tutorial will guide you through configuring a cloud-based Linux desktop +accessible from any device with a web browser and HTML5 support.</p> + +<h2>High-level overview</h2> +<p>We'll be using the following software and services to make this work:</p> +<ul> + <li><a href="http://www.gandi.net/">Gandi.net cloud hosting</a></li> + <li><a href="">Ubuntu Linux</a> as the operating system</li> + <li><a href="">vnc4server</a> to create the X session and share it via VNC</li> + <li><a href="">Apache Tomcat</a> as the web application server</li> + <li><a href="http://guac-dev.org/">Guacamole</a> to convert the VNC session to HTML</li> +</ul> + +<p>This tutorial was based on the following resources:</p> +<ul> + <li> + <a href="http://guac-dev.org/doc/gug/users-guide.html">The Guacamole user's guide + </li> + <li><a href="https://coddswallop.wordpress.com/2012/05/09/ubuntu-12-04-precise-pangolin-complete-vnc-server-setup/">VNC server setup</a></li> + <li><a href="https://www.digitalocean.com/community/tutorials/how-to-create-a-ssl-certificate-on-apache-on-arch-linux"> + How To Create a SSL Certificate</a></li> +</ul> + +<h2>Creating the VPS instance</h2> +<p>First, visit http://www.gandi.net and register an account.</p> +<p>After you login to your account, open the My Account page and select +the Services tab and then the Servers sub-tab. From the server control +panel, select Create a Server</p> +<img src="images/01.jpg" alt='Servers page' width="50%"> +<p>How you configure the server will depend on what you plan to use it for. +For very simple applications, the lowest settings will suffice, but for heavier +loads you may need to increase these. Higher settings will increase the hourly +fee. These settings can always be changed later, but some starting estimates +are included below:</p> +<p>For a simple Visual Basic 6 application (ex: <em>Organizer's Database</em>)</p> +<ul> + <li><strong>CPU Cores</strong>: <em>1</em></li> + <li><strong>RAM</strong>: <em>256MB</em></li> + <li><strong>Disk space</strong>: <em>3GB</em></li> +</ul> +<p>For a remote office desktop system</p> +<ul> + <li><strong>CPU Cores</strong>: <em>2</em></li> + <li><strong>RAM</strong>: <em>1024MB</em></li> + <li><strong>Disk space</strong>: <em>10GB</em></li> +</ul> +<p>You will probably always want 1 interface, and IPv4 enabled</p> +<img src="images/02.jpg" alt='Hardware configuration page' width="50%"> +<p>On the next page you will choose the server software configuration.</p> +<ul> + <li><strong>Type of image</strong>: <em>Gandi Image</em></li> + <li><strong>OS</strong>: <em>Ubuntu 12.04 32 bits</em></li> + <li><strong>Name</strong>: Choose any name for your server</li> + <li><strong>Means of Authentication</strong>: <em>Password</em></li> +</ul> +<img src="images/03.jpg" alt='Software configuration page' width="50%"> +<p>Once the server is created, you can hover the mouse cursor over the +information symbol beside the hostname in your server control panel to +show the server's IP address. For the next section of the tutorial, you +will need to SSH to this address. For Linux or Mac OS X users, simply +open a terminal window and type 'ssh admin@<em>[ip address]</em>' +Windows users can connect using +<a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html">PuTTY</a>. +<h2>Installing the software</h2> +<p>Install the prerequisites. For the <em>su</em> command, you will use the +same password that you used to connect to the SSH session.</p> +<pre> +su - +apt-get update +apt-get upgrade +apt-get install tomcat7 vnc4server +apt-get install libcairo2-dev libjpeg62-dev libpng12-dev libossp-uuid-dev +apt-get install libssh2-1-dev libvncserver-dev libssl-dev +apt-get install guacamole +apt-get install apache2 ufw openbox xterm +</pre> + +<p>Download and deploy the guacamole Tomcat application</p> +<pre> +wget http://downloads.sourceforge.net/project/guacamole/current/binary/guacamole-0.9.8.war?r=http%3A%2F%2Fguac-dev.org%2Frelease%2Frelease-notes-0-9-8&ts=1443744824&use_mirror=superb-dca2 +mv guacamole-0.9.8.war* /var/lib/tomcat7/webapps/guacamole-0.9.8.war + +mkdir /usr/share/tomcat7/.guacamole +ln -s /etc/guacamole/guacamole.properties /usr/share/tomcat7/.guacamole/ +chmod 644 /etc/guacamole/user-mapping.xml + +/etc/init.d/tomcat7 restart +</pre> + + +<p>Update to the latest guacamole install (Yes, it was already installed via +apt-get...but I couldn't get that version to work. It does help by getting some +of the configuration set up though!)</p> +<pre> +apt-get install build-essential +wget http://downloads.sourceforge.net/project/guacamole/current/source/guacamole-server-0.9.8.tar.gz?r=http%3A%2F%2Fguac-dev.org%2Frelease +mv *guacamole-server-0.9.8.tar.gz* guacamole-server-0.9.8.tar.gz +tar -xzvf guacamole-server-0.9.8.tar.gz +cd guacamole-server-0.9.8/ +./configure --with-init-dir=/etc/init.d +make +make install +</pre> + +<h2>Configuration</h2> + +<p>Generate an SSL certificate to secure your connection</p> +<pre> +openssl genrsa -des3 -out /etc/ssl/private/guacd.key 2048 +openssl req -new -key /etc/ssl/private/guacd.key -out /etc/ssl/private/guacd.csr +cp /etc/ssl/private/guacd.key /etc/ssl/private/guacd.key.org +openssl rsa -in /etc/ssl/private/guacd.key.org -out /etc/ssl/private/guacd.key +openssl x509 -req -days 365 -in /etc/ssl/private/guacd.csr -signkey /etc/ssl/private/guacd.key -out /etc/ssl/certs/guacd.crt +</pre> + +<p>Configure the firewall</p> +<pre> +ufw allow 22 +ufw allow 443 +ufw default deny +ufw enable +</pre> + +<p>Configure apache for SSL support</p> +<pre> +a2enmod ssl +a2enmod proxy +a2enmod proxy_http +a2ensite default-ssl +service apache2 restart +</pre> +<pre>nano /etc/apache2/sites-enabled/default-ssl.conf</pre> +<pre> +<IfModule mod_ssl.c> +<VirtualHost _default_:443> + ProxyPass / http://localhost:8080/ + ProxyPassreverse / http://localhost:8080/ +... + SSLCertificateFile /etc/ssl/certs/guacd.crt + SSLCertificateKeyFile /etc/ssl/private/guacd.key +... +</pre> + +<p>Configure GUACAMOLE_HOME</p> +<pre> +echo "export JAVA_HOME=/usr/lib/jvm/default-java" >> ~/.bashrc +echo "export CATALINA_HOME=/var/lib/tomcat7" >> ~/.bashrc +echo "export GUACAMOLE_HOME=/etc/guacamole" >> ~/.bashrc +bash +</pre> + +<p>Update your Guacamole user configuration.</p> +<ul> + <li><strong>GUAC-USER</strong>: The username you will use to login</li> + <li><strong>GUAC-PASS-MD5</strong>: The password you will use to login, as + an MD5 hash (<a href="http://www.miraclesalad.com/webtools/md5.php"> + MD5 hash calculator</a>)</li> + <li><strong>VNCPASS</strong>: The password you will configure for the VNC server</li> +</ul> +<pre>nano /etc/guacamole/user-mapping.xml</pre> +<pre> +<user-mapping> + + <authorize + username="GUAC-USER" + password="GUAC-PASS-MD5" + encoding="md5"> + <protocol>vnc</protocol> + <param name="hostname">localhost</param> + <param name="port">5901</param> + <param name="password">VNCPASS</param> + </authorize> + +</user-mapping> +</pre> +<p>Update your guacd configuration</p> +<pre>nano /etc/guacamole/guacd.conf</pre> +<pre> +# +# guacd configuration file +# + +[daemon] + +pid_file = /var/run/guacd.pid +log_level = info + +[server] + +bind_host = localhost +bind_port = 4822 +</pre> + +<p>Update guacamole.properties auth provider</p> +<pre> +# Hostname and port of guacamole proxy +guacd-hostname: localhost +guacd-port: 4822 + +# Auth provider class (authenticates user/pass combination, needed if using the provi$ +#auth-provider: net.sourceforge.guacamole.net.basic.BasicFileAuthenticationProvider +user-mapping: /etc/guacamole/user-mapping.xml +</pre> + +<p>Allow DHCP so you can destroy the network interface while not in use</p> +<pre>nano /etc/default/gandi</pre> +<pre> +# set a list of network interfaces which should not be configured by DHCP +# if you attach a interface setup in your private VLAN, you should consider +# adding the interface here. If you have multiple interfaces, use space as +# separator. +# ex : CONFIG_NODHCP="eth1 eth2" +#CONFIG_NODHCP="eth0" +CONFIG_NODHCP="" +</pre> + +<p>Configure the VNC server</p> +<pre>vncserver</pre> +<pre>nano ~/.vnc/xstartup</pre> +<pre> +[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup +[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources +xsetroot -solid grey +x-window-manager & +</pre> + +<p>Start the server</p> +<pre> +vncserver -geometry 1024x768 -depth 8 +</pre> + +<p>Start the vnc sever when the system reboots</p> +<pre>nano ~/boot.sh</pre> +<pre> +~/.bashrc +/etc/init.d/apache2 start +/etc/init.d/guacd start +/etc/init.d/tomcat7 start +</pre> +<pre>crontab -e</pre> +<pre> +@reboot /root/boot.sh +@reboot vncserver -geometry 1024x768 -depth 8 +</pre> + +<p>Update your system and restart the services!</p> +<pre> +apt-get install gandi-hosting-vm2 +apt-get update +apt-get upgrade +/etc/init.d/apache2 restart +/etc/init.d/guacd restart +/etc/init.d/tomcat7 restart +</pre> + +<p>Open your browser and navigate to your server at: +https://<em>SERVER IP ADDRESS</em>/guacamole-0.9.8</p> + +<h3>Troubleshooting</h3> +<p>If you encounter any problems getting this working, check for errors +in the following files:</p> + +<pre> +/var/log/tomcat7/catalina.out +/var/log/syslog +/var/log/apache2/error.log +~/.vnc/*.log +</pre> + +<p>Also be sure to check the servers are running</p> +<pre> +/etc/init.d/apache2 status +/etc/init.d/guacd status +/etc/init.d/tomcat7 status +</pre> + +<p>If you receive an error that the login is incorrect and you have verified that +you are using the correct login specified in your user-mapping.xml file, try +restarting the tomcat server.</p> +<pre>/etc/init.d/tomcat7 restart</pre> + +</body> +</html> \ No newline at end of file diff --git a/webdesktop-source/02_vb6.html b/webdesktop-source/02_vb6.html new file mode 100755 index 0000000..a3c9699 --- /dev/null +++ b/webdesktop-source/02_vb6.html @@ -0,0 +1,56 @@ +<html> + <head> + <title>Installing Visual Basic 6</title> + <link rel="icon" type="image/png" href="/favicon.png"> + <meta name="title" content="Adding Visual Basic 6"> + <meta name="description" content="This section will guide you through + installing the Visual Basic 6 runtime for running VB6 applications on + the cloud desktop."> + <style> + pre + { + background-color: #CCC; + padding: .3em; + margin: .2em; + } + </style> + </head> + +<body> +<h1>Adding VB6</h1> + +<p>This tutorial will guide you through installing Visual Basic 6 on a +VPS server like web desktop. This is designed for systems running +<em>Ubuntu 12.04 x32</em></p> + +<h2>Preparation</h2> +<p>Since the Visual Basic installation is a graphical program, these +steps need to be performed from a GUI. Login through Guacamole, then +right-click anywhere on the desktop to open the software menu and +launch the terminal emulator.</p> +<img src="images/vb-01.jpg" width="50%"/> + +<h2>Installing VB6</h2> +<p>First, install the requried prerequisite software</p> +<pre> +apt-get install wine unzip +</pre> + +<p>Next, download the VB6 runtime</p> +<pre> +wget -O vb6runtime.zip http://downloads.sourceforge.net/project/vb6extendedruntime/Visual%20Basic%206.0%20Extended%20Runtime%201.5.1.zip?r=&ts=1443993940&use_mirror=skylineservers +unzip vb6runtime.zip +wine ./VB6\ Extended\ Runtime\ Setup\ 1.5.1.exe +</pre> +<img src="images/vb-02.jpg" width="50%"/> +<img src="images/vb-03.jpg" width="50%"/> + +<p>Finally, fix the missing expsrv.dll</p> +<pre> +wget -O expsrv.zip http://downloads.dlldll.com/dllfiles/expsrv.dll.zip +unzip expsrv.zip +mv expsrv.dll ~/.wine/drive_c/windows/system32 +</pre> + +</body> +</html> \ No newline at end of file diff --git a/webdesktop-source/03_odb.html b/webdesktop-source/03_odb.html new file mode 100755 index 0000000..9ce8181 --- /dev/null +++ b/webdesktop-source/03_odb.html @@ -0,0 +1,60 @@ +<html> + <head> + <title>Installing Organizer's Database</title> + <link rel="icon" type="image/png" href="/favicon.png"> + <meta name="title" content="Adding Organizer's Database"> + <meta name="description" content="This section will cover installing the + Organizer's Database application to the cloud desktop."> + <style> + pre + { + background-color: #CCC; + padding: .3em; + margin: .2em; + } + </style> + </head> + +<body> +<h1>Installing Organizer's Database</h1> + +<p>This tutorial will guide you through installing the Organizer's Database +application on the cloud desktop.</p> + +<h2>Preparation</h2> +<p>You should have already completed the initial setup and Visual Basic 6 +setup tutorials on this system.</p> +<p>You should also create a .zip file containing your entire ODB installation. +For example, if your odb.exe is located at C:\ODB\odb.exe, you should create +a .zip file of the entire C:\ODB directory.</p> + +<h2>Uploading ODB</h2> +<p>There are many ways to upload your ODB zip file to the server. If you are +able to use SCP, that is probably the quickest. But since that is not available +on all systems, I will explain a simpler method here.</p> + +<p>First, install and run Firefox on your cloud desktop.</p> +<pre> +apt-get install firefox +firefox +</pre> + +<p>Next, use a webmail provider like Gmail, Yahoo mail, or many corporate or +organization email services. Or you can use a file upload service like +dropbox. Upload the ODB zip file and use Firefox inside your web desktop +session to retrieve the file.</p> + +<h2>Installing ODB</h2> + +<p>Now you simply unzip the file and place it at the correct path.</p> +<pre> +unzip odb.zip +mv -R odb/ ~/.wine/drive_c/ +~/.wine/drive_c/odb/odb.exe +</pre> + +<img src="images/odb-01.jpg" width="50%"/> + + +</body> +</html> \ No newline at end of file diff --git a/webdesktop-source/04_office.html b/webdesktop-source/04_office.html new file mode 100755 index 0000000..6dfadf9 --- /dev/null +++ b/webdesktop-source/04_office.html @@ -0,0 +1,49 @@ +<html> + <head> + <title>Installing basic office software</title> + <link rel="icon" type="image/png" href="/favicon.png"> + <meta name="title" content="Installing basic office software"> + <meta name="description" content="This section will cover configuring the + web desktop for a standard office desktop"> + <style> + pre + { + background-color: #CCC; + padding: .3em; + margin: .2em; + } + </style> + </head> + +<body> +<h1>Installing basic office software</h1> + +<p>This tutorial will guide you through configuring a standard set of +office tools in the web desktop environment. You probably want two cores +and at least 1024MB of ram on the server for this software.</p> + +<h2>Install the software</h2> +<p>Install a simpler desktop environment</p> +<pre>apt-get install kubuntu-desktop</pre> + +<p>Install an office suite</p> +<pre>apt-get install libreoffice</pre> + +<p>Install a web browser and mail client</p> +<pre>apt-get install firefox thunderbird</pre> + +<h2>Configure the VNC</h2> +<pre>nano ~/.vnc/xstartup</pre> +<pre> +... +#x-window-manager & +startkde & +</pre> + +<h2>The desktop</h2> +<img src="images/office-01.jpg" width="50%"/> +<img src="images/office-02.jpg" width="50%"/> + + +</body> +</html> \ No newline at end of file diff --git a/webdesktop-source/description b/webdesktop-source/description new file mode 100644 index 0000000..bf28583 --- /dev/null +++ b/webdesktop-source/description @@ -0,0 +1 @@ +Old instruction for creating a compatibility tool for running old VB6 apps through a cloud desktop diff --git a/webdesktop-source/images/01.jpg b/webdesktop-source/images/01.jpg new file mode 100644 index 0000000..232a6ff Binary files /dev/null and b/webdesktop-source/images/01.jpg differ diff --git a/webdesktop-source/images/02.jpg b/webdesktop-source/images/02.jpg new file mode 100644 index 0000000..2f3e586 Binary files /dev/null and b/webdesktop-source/images/02.jpg differ diff --git a/webdesktop-source/images/03.jpg b/webdesktop-source/images/03.jpg new file mode 100644 index 0000000..f708922 Binary files /dev/null and b/webdesktop-source/images/03.jpg differ diff --git a/webdesktop-source/images/04.jpg b/webdesktop-source/images/04.jpg new file mode 100644 index 0000000..391516c Binary files /dev/null and b/webdesktop-source/images/04.jpg differ diff --git a/webdesktop-source/images/05.jpg b/webdesktop-source/images/05.jpg new file mode 100644 index 0000000..076463b Binary files /dev/null and b/webdesktop-source/images/05.jpg differ diff --git a/webdesktop-source/images/odb-01.jpg b/webdesktop-source/images/odb-01.jpg new file mode 100644 index 0000000..6ee521a Binary files /dev/null and b/webdesktop-source/images/odb-01.jpg differ diff --git a/webdesktop-source/images/office-01.jpg b/webdesktop-source/images/office-01.jpg new file mode 100644 index 0000000..8c01921 Binary files /dev/null and b/webdesktop-source/images/office-01.jpg differ diff --git a/webdesktop-source/images/office-02.jpg b/webdesktop-source/images/office-02.jpg new file mode 100644 index 0000000..62bfc0d Binary files /dev/null and b/webdesktop-source/images/office-02.jpg differ diff --git a/webdesktop-source/images/vb-01.jpg b/webdesktop-source/images/vb-01.jpg new file mode 100644 index 0000000..4a4c685 Binary files /dev/null and b/webdesktop-source/images/vb-01.jpg differ diff --git a/webdesktop-source/images/vb-02.jpg b/webdesktop-source/images/vb-02.jpg new file mode 100644 index 0000000..c480221 Binary files /dev/null and b/webdesktop-source/images/vb-02.jpg differ diff --git a/webdesktop-source/images/vb-03.jpg b/webdesktop-source/images/vb-03.jpg new file mode 100644 index 0000000..5015135 Binary files /dev/null and b/webdesktop-source/images/vb-03.jpg differ diff --git a/webdesktop-source/index.php b/webdesktop-source/index.php new file mode 100755 index 0000000..8d386c1 --- /dev/null +++ b/webdesktop-source/index.php @@ -0,0 +1,52 @@ +<html> + <head> + <link rel="icon" type="image/png" href="/favicon.png"> + <title>Slightly Cyberpunk | Tutorials | Web Desktop Source</title> + <meta name="title" content="Web Desktop Source" /> + <meta name="description" content="Configuring your own cloud-based desktop + environment accessible from any device with an HTML5-capable web browser" /> + <style> + h1 + { + text-align: center; + } + + ul + { + list-style-type: none; + } + + ul ul + { + list-style-type: disc; + margin-left: -2em; + } + + ul ul li + { + margin-left: 2em; + } + </style> + </head> + <body> + <h1>Web Desktop Tutorials</h1> + + <ul> + <?php + $files = scandir("."); + foreach($files as $file) + { + $meta = get_meta_tags($directory."$file"); + if( $file != "index.php" && $meta ) + { + $title = $meta['title']; + $description = $meta['description']; + echo "<li><a href='$file'>$title</a>: $description</li>"; + } + } + + ?> + </ul> + + </body> +</html> \ No newline at end of file