Blog

Subscribe with RSS to keep up with the latest news. For site changes, see the changelog kept with the code base.


Managing your $HOME with git without symlinks


Overview

Based off the thread found at https://news.ycombinator.com/item?id=11071754

This relatively simple setup allows you to manage your dot files with just git and without having to resort to symlinks or some other hackery.

New Setup

  1. Create your git working directory
    git init --bare ${HOME}/.config/dotfiles
    
  2. Add an alias to git which will only be used for working with your dot files
    alias dotgit='/usr/bin/git --git-dir=${HOME}/.config/dotfiles/ --work-tree=${HOME}'
    
  3. Ignore your .git directory to avoid headaches
    echo "${HOME}/.config/dotfiles" > ${HOME}/.gitignore
    
  4. Ignore untracked files by default, this will make ‘dotgit status’ a lot less noisy
    dotgit config --local status.showUntrackedFiles no
    
  5. Link your repo to a remote repository for easy backups
    dotgit remote add origin <GIT_URI>
    

Importing an existing repository onto a new system

  1. Add the alias to git which will only be used for working with your dot files
    alias dotgit='/usr/bin/git --git-dir=${HOME}/.config/dotfiles/ --work-tree=${HOME}'
    
  2. Ignore your .git directory to avoid headaches
    echo "${HOME}/.config/dotfiles" > ${HOME}/.gitignore
    
  3. Clone the repository
    git clone --bare <GIT_URI> ${HOME}/.config/dotfiles
    
  4. Check out the code
    dotgit checkout
    

    WARNING: This might throw the following error if some of the files to checkout already exist:

    error: The following untracked working tree files would be overwritten by checkout:
      .bashrc
    Please move or remove them before you can switch branches.
    Aborting
    

    You’ll need to delete the mentioned files and retry the check out.

  5. Ignore untracked files by default, this will make ‘dotgit status’ a lot less noisy
    dotgit config --local status.showUntrackedFiles no
    

Usage

Once the setup is completed you can interact with it like you would any git repository.

dotgit add .bashrc
dotgit commit -m 'adding .bashrc'
dotgit push

Simplifying Apache httpd setup with mod_macro


For Apache httpd setups with numerous virtual hosts there can be a lot of config redundancy. This can be alleviated by using mod_macro (as of httpd 2.4.6 this is a default Apache httpd module, for older versions it can be downloaded from https://people.apache.org/~fabien/mod_macro/).

Here are my configs using mod_macro (currently I run httpd 2.2.x, these configs are made for this version of httpd). This assumes you have a central web root of /home/web/DOMAIN/SUBDOMAIN, so subdomain.domain.com would be at /home/web/domain.com/subdomain.

First a common macro for all virtual hosts:

<Macro vhost-common $subdomain $domain>
    ServerAdmin webmaster@$domain
    ServerName $subdomain.$domain
    DocumentRoot /home/web/$domain/$subdomain/htdocs/
    LogLevel error
    ErrorLog "|rotatelogs /home/web/$domain/$subdomain/logs/error.%Y%m%d.log 86400"
    CustomLog "|rotatelogs /home/web/$domain/$subdomain/logs/access.%Y%m%d.log 86400" combined

    <IfModule mod_rewrite.c>
        RewriteLogLevel 0
        RewriteLog "|rotatelogs /home/web/$domain/$subdomain/logs/rewrite.%Y%m%d.log 86400"
    </IfModule>
    <IfModule mod_jk.c>
        JkLogLevel info
        JkLogFile "|rotatelogs /home/web/$domain/$subdomain/logs/mod_jk.%Y%m%d.log 86400"
    </IfModule>
    <Directory />
        order deny,allow
        deny from all
    </Directory>
    <Directory /home/web/$domain/$subdomain>
        order allow,deny
        allow from all
    </Directory>
    Header always set X-Frame-Options DENY
    Header always set X-Content-Type-Options nosniff
</Macro>

Next we need a config that is used for any HTTP vhost:

<Macro vhost-http $subdomain $domain $port>
    <VirtualHost *:$port>
        Use vhost-common $subdomain $domain
    </VirtualHost>
</Macro>

And a config that is used for any HTTPS vhost:

<Macro vhost-https $subdomain $domain $port>
    <IfModule mod_ssl.c>
    <VirtualHost *:$port>
        Use common $subdomain $domain

        SSLEngine on
        SSLProtocol all -SSLv2 -SSLv3
        SSLHonorCipherOrder on
        SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
        SSLCompression Off
        SSLCertificateFile /home/web/$domain/$subdomain/ssl/$subdomain.$domain.pem
        SSLCertificateKeyFile /home/web/$domain/$subdomain/ssl/$subdomain.$domain.key
        SSLCACertificateFile /home/web/$domain/$subdomain/ssl/cas.pem

        BrowserMatch "MSIE [2-6]" \
            nokeepalive ssl-unclean-shutdown \
            downgrade-1.0 force-response-1.0
        # MSIE 7 and newer should be able to use keepalive
        BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
    </VirtualHost>
    </IfModule>
</Macro>

VirtualHosts can then be spun up with just:

Use vhost-http subdomain domain.com 80

or

Use vhost-https subdomain domain.com 443

Using Tomcat’s CATALINA_BASE & CATALINA_HOME for multiple instances


Tomcat supports having multiple instances from a single installation by using the CATALINA_BASE & CATALINA_HOME directories. CATALINA_BASE is the installation root, while CATALINA_HOME is the instance root. Using these two variables and a few symbolic links it’s easy to support quick & easy changes between patch levels (and even major revisions) of Tomcat without having to re-install & re-configure application/deployment level changes.

Assuming we unpack the default Apache Tomcat 8 tarball (latest version at time of this is 8.0.24) at /usr/local/share/apache-tomcat-8.0.24 (we’ll reference this as ${TOM_BASE} from now on) we can set things up to support numerous Tomcat 8 instances from this single installation as follows.

For this case we’ll assume we’re installing 2 instances at ~/tomcat/instance0 and ~/tomcat/instance1.

First you need to create the directories for the instances and some required instance specific directories:

for DIR in ~/tomcat/instance0 ~/tomcat/instance1; do
    mkdir -p \
        ${DIR}/bin \
        ${DIR}/conf \
        ${DIR}/lib \
        ${DIR}/logs \
        ${DIR}/temp \
        ${DIR}/webapps \
        ${DIR}/work
done

Each instance needs it’s own copy of conf/server.xml:

cp ${TOM_BASE}/conf/server.xml ~/tomcat/instance0/conf/server.xml
cp ${TOM_BASE}/conf/server.xml ~/tomcat/instance1/conf/server.xml

The following files are also needed for each instance, but they can be symbolic links as they don’t need to vary between instances (you could also copy them instead of symbolic linking them if you want to support different settings like log levels):

for DIR in ~/tomcat/instance0 ~/tomcat/instance1; do
    for FILE in \
        bin/tomcat-juli.jar \
        bin/catalina.sh \
        bin/daemon.sh \
        bin/digest.sh \
        bin/setclasspath.sh \
        bin/shutdown.sh \
        bin/startup.sh \
        bin/tool-wrapper.sh \
        bin/version.sh \
        conf/catalina.properties \
        conf/logging.properties \
        conf/web.xml
    do
        ln -sf ${TOM_BASE}/${FILE} ~/tomcat/instance0/${FILE}
        ln -sf ${TOM_BASE}/${FILE} ~/tomcat/instance1/${FILE}
    done
done

For each instance to be able to run in parallel you’ll need to edit their respective conf/server.xml files to ensure that the ports from one instance don’t conflict with any other instances.

Finally you need to set the CATALINA_BASE & CATALINA_HOME environment variables for each instance for this setup to work properly. Tomcat will automatically source bin/setenv.sh on start up if it’s present, so we’ll use that to set these variables properly.

~/tomcat/instance0/bin/setenv.sh:

CATALINA_BASE=/usr/local/share/apache-tomcat-8.0.24
CATALINA_HOME=${HOME}/tomcat/instance0

~/tomcat/instance1/bin/setenv.sh:

CATALINA_BASE=/usr/local/share/apache-tomcat-8.0.24
CATALINA_HOME=${HOME}/tomcat/instance1

You’re now ready to run both instances in parallel by running their specific startup.sh:

~/tomcat/instance0/bin/startup.sh
~/tomcat/instance1/bin/startup.sh

When the time comes to upgrade Apache Tomcat to the next version you can now just unpack the tarball to a shared directory, update the instances’s bin/setenv.sh that you want to upgrade, and re-run the symbolic link loop above to re-link everything to the new shared install.

One note of importance, conf/server.xml should remain the same between patch levels but can be quite different between major versions (8.x.x to 9.x.x), so I suggest overwriting server.xml with the fresh one and re-applying your changes when doing major version changes of Apache Tomcat.

Scripted versions of the above setup are at the following download links.


Want to see more? See the Blog Archive.