Skip to content

Instantly share code, notes, and snippets.

@pwillis-els
Created September 20, 2019 14:56
Show Gist options
  • Save pwillis-els/567404495b984b2115e99cb91ae01ec6 to your computer and use it in GitHub Desktop.
Save pwillis-els/567404495b984b2115e99cb91ae01ec6 to your computer and use it in GitHub Desktop.
Fix Jenkins to stop running from a ".jenkins" hidden directory

Fixing Jenkins to stop adding /.jenkins to your JENKINS_HOME path

When running Jenkins, you may try to set the JENKINS_HOME path that Jenkins uses at start-up, only to find the following output message:

Jenkins home directory: /var/jenkins_home/.jenkins found at: $user.home/.jenkins

You're trying to get Jenkins to read its files from /var/jenkins_home, but it keeps tacking on a /.jenkins hidden folder, and you can't get it to stop.

You've googled around and read all the documentation, but none of it describes how to fix this.

The actual problem can be found in the Jenkins source code found here on GitHub:

    public FileAndDescription getHomeDir(ServletContextEvent event) {
        // check JNDI for the home directory first
        for (String name : HOME_NAMES) {
            try {
                InitialContext iniCtxt = new InitialContext();
                Context env = (Context) iniCtxt.lookup("java:comp/env");
                String value = (String) env.lookup(name);
                if(value!=null && value.trim().length()>0)
                    return new FileAndDescription(new File(value.trim()),"JNDI/java:comp/env/"+name);
                // look at one more place. See issue #1314
                value = (String) iniCtxt.lookup(name);
                if(value!=null && value.trim().length()>0)
                    return new FileAndDescription(new File(value.trim()),"JNDI/"+name);
            } catch (NamingException e) {
                // ignore
            }
        }

        // next the system property
        for (String name : HOME_NAMES) {
            String sysProp = SystemProperties.getString(name);
            if(sysProp!=null)
                return new FileAndDescription(new File(sysProp.trim()),"SystemProperties.getProperty(\""+name+"\")");
        }

        // look at the env var next
        for (String name : HOME_NAMES) {
            String env = EnvVars.masterEnvVars.get(name);
            if(env!=null)
                return new FileAndDescription(new File(env.trim()).getAbsoluteFile(),"EnvVars.masterEnvVars.get(\""+name+"\")");
        }

        // otherwise pick a place by ourselves

        String root = event.getServletContext().getRealPath("/WEB-INF/workspace");
        if(root!=null) {
            File ws = new File(root.trim());
            if(ws.exists())
                // Hudson <1.42 used to prefer this before ~/.hudson, so
                // check the existence and if it's there, use it.
                // otherwise if this is a new installation, prefer ~/.hudson
                return new FileAndDescription(ws,"getServletContext().getRealPath(\"/WEB-INF/workspace\")");
        }

        File legacyHome = new File(new File(System.getProperty("user.home")),".hudson");
        if (legacyHome.exists()) {
            return new FileAndDescription(legacyHome,"$user.home/.hudson"); // before rename, this is where it was stored
        }

        File newHome = new File(new File(System.getProperty("user.home")),".jenkins");
        return new FileAndDescription(newHome,"$user.home/.jenkins");
    }

This code is doing a couple things:

  • Check for a name matching the 'HOME_NAMES' list in the lookup for JNDI environment variables
  • Check 'SystemProperties' for the same names
  • Check 'EnvVars' for the same thing
  • Check for a '/WEB-INF/workspace' directory in the Servlet's current context
  • Check for a 'user.home'/.hudson directory
  • Finally, just default to 'user.home'/.jenkins

I'm not a Java developer, so I couldn't understand most of how it was looking up JNDI, SystemProperties, or EnvVars. However, I did happen upon this Oracle page about using JNDI: https://docs.oracle.com/javase/jndi/tutorial/beyond/env/source.html

Apparenty you can set SystemProperties by adding the -D option on the command-line to Java. So, let's try adding -DJENKINS_HOME=/var/jenkins_home:

java -DJENKINS_HOME=/var/jenkins_home -Djenkins.install.runSetupWizard=false -Djenkins.model.Jenkins.slaveAgentPort=50000 -Djenkins.model.Jenkins.slaveAgentPortEnforce=true -Dio.jenkins.dev.security.createAdmin= -Dio.jenkins.dev.security.allowRunsOnMaster= -Dhudson.model.LoadStatistics.clock=1000 -Djava.awt.headless=true -jar /var/jenkins_home/jenkins.war --webroot=/var/jenkins_home/war

Some time later:

Jenkins home directory: /var/jenkins_home found at: SystemProperties.getProperty("JENKINS_HOME")

Voila! No more '.jenkins' directory!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment