Generating SSH keys for 'apache' user

PhpApacheGitGithubSsh Keys

Php Problem Overview


How do I add SSH keys for 'apache' user in Linux?

BACKGROUND

I am trying to add a service hook to github to notify a URL once I push to my repo. I have the following php page set up:

<?php `git pull origin master`;  

However I get the following output:

sh: git: Permission denied

This is because the keys I generated for github access were generated by my 'root' user. However when I exectue a command from php it is the 'apache' user that runs it.

The keys therefore do not correspond and permission is denied to pull.

As I cannot switch user from the terminal to generate keys as 'apache', I am not too sure what to do. Can anyone suggest a solution?

Php Solutions


Solution 1 - Php

You may have to copy the root generated keys in the .ssh directory of your apache user.

Assuming the homedir of apache is /var/www (check /etc/passwd) and the named key is id_rsa-git :

mkdir -p /var/www/.ssh/
cp /root/.ssh/id_rsa-git /var/www/.ssh/id_rsa

No need to copy the public key.

Note : by default the key used are id_rsa or id_dsa. You may change the name of the copied key to match this.

You may also change ownership of the id_rsa key and .ssh directory:

chown -R apache:apache /var/www/.ssh
chmod 0700 /var/www/.ssh
chmod 0600 /var/www/.ssh/id_rsa

Solution 2 - Php

As you are root, you can try it sudo -u apache ssh-keygen -t rsa

Solution 3 - Php

Just posting the comment of @KitCarrau, under yvan's answer, that worked for me

sudo -u apache ssh-keygen -t rsa

for debian

sudo -u www-data ssh-keygen -t rsa

after this click Enter twice, to skip passphrase

also, it suggests to create the public/private keys in /var/www/.ssh directory, even if I had my www direcotry in /home/my_user/www, that is fine.

Solution 4 - Php

The existing answers are either incomplete or insecure. If you put your .ssh directory into the home directory of the apache user (/var/www) then this will also most likely serve the contents of that directory and thus expose your ssh private key to the public web. To prevent this you'd have to configure apache not to serve the .ssh directory but none of the existing answers explains how to do this.

I'd also argue that it is still dangerous to have your .ssh directory be a subdirectory of your publicly served www-root because even if you add a rule to your apache config, upgrading the server or doing unrelated other configurations might override this rule without you noticing.

So here is an answer that puts the key elsewhere, where it is not served by apache by default. There is not even the need to ever become the www-data user as others are struggling with.

First, find out the home directory of our apache user, for example by looking into /etc/passwd and looking for the www-data user or however the apache user of your distribution is called. The home directory is likely /var/www.

Then run (replacing /var/www with the home directory of the apache user on your setup):

$ mkdir "$HOME/www-data.ssh"
$ ssh-keygen -q -t rsa -f "$HOME/www-data.ssh/id_rsa" -N ""
$ chown -R www-data:www-data "$HOME/www-data.ssh"
$ mkdir /var/www/.ssh
$ cat << END > /var/www/.ssh/config
> Host *
>     IdentityFile $HOME/www-data.ssh/id_rsa
> END
$ chown -R www-data:www-data /var/www/.ssh

Now your www-data user will use the ssh key in $HOME/www-data.ssh/id_rsa for all its ssh connections and since your $HOME is probably different from /var/www, that directory will not be served. So even without adding any custom rules to apache, users will be able to see your .ssh/config but they will not be able to access the private key it points to. Nevertheless, your www-data user will know how to do it.

Solution 5 - Php

I ran into a similar issue and there is one extra snag. In order to ssh using the apache user you also need to edit the /etc/passwd file so that the directive for apache has a shell defined.

In my case I needed to change

apache:x:48:48:Apache:/var/www:/sbin/nologin

to

apache:x:48:48:Apache:/var/www:/bin/bash

Solution 6 - Php

To add to @Vincent, if you have SELinux enabled, you'll have to set the context for the new .ssh folder.

On RHEL, add the following to this file: /etc/selinux/targeted/contexts/files/file_contexts.homedirs

/var/www/[^/]*/.+       system_u:object_r:user_home_t:s0
/var/www/[^/]*/\.ssh(/.*)?      system_u:object_r:ssh_home_t:s0

And then run the command

# restorcon -Rv /var/www/

Solution 7 - Php

I don't know if this will work on redhat (I assume that is what you're running) however, I was able to su to www-data (the apache user for debian) by executing the following:

sudo su www-data

it actually worked shrugs go figure

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKitView Question on Stackoverflow
Solution 1 - PhpVincentView Answer on Stackoverflow
Solution 2 - PhpyvanView Answer on Stackoverflow
Solution 3 - PhpdavView Answer on Stackoverflow
Solution 4 - PhpjoschView Answer on Stackoverflow
Solution 5 - PhpdkinzerView Answer on Stackoverflow
Solution 6 - PhpJim HowardView Answer on Stackoverflow
Solution 7 - PhpThomas WrightView Answer on Stackoverflow