I am attempting to set up a Tor hidden service on CentOS 7 (with systemd), using the tor package from the EPEL repository.

Previously this was working fine until a few days ago when it stopped working. Nothing on the system was restarted at this time, though automatic updates are enabled via yum-cron so perhaps something updated.

However, for what it's worth, I have also seen this issue on a mostly-stock installation of Fedora Server and on Fedora Workstation.

Now when I attempt to start the tor service with the hidden service lines in the /etc/tor/torrc file, it fails to start.

I have been checking error messages using journalctl -xn, and they are not consistent - however the primary errors seem to be:

Nov 09 22:05:18 hostname tor[7561]: Nov 09 22:05:18.245 [warn] Directory /var/lib/tor/sshservice/ cannot be read: Permission denied

and sometimes:

Nov 09 22:12:33.119 [warn] /var/lib/tor/sshservice/ is not owned by this user (root, 0) but by toranon (997). Perhaps you are running Tor as the wrong user

I have ensured the following about the entire /var/lib/tor path, but with no success:

  • Directory is owned by user/group toranon (default tor user for the EPEL package)
  • Permissions are set appropriately (I have tried 700, 770, 600, 660) on the directory.
  • SELinux contexts are set appropriately for the directory and I have verified this using restorecon.

Other info:

  • If I change ownership of the directory to root, I recieve the same "wrong user" message as before, but with the usernames reversed.
  • I have attempted to disable SELinux completely and verified that the tor service still does not start.
  • The hidden service directory is already populated with the private key and hostname files, and they were created by the tor daemon on this system. This configuration previously fully worked.
  • If I completely remove the HiddenServiceDir and HiddenServicePort lines from the config, tor starts up as expected.

Some potentially helpful output from /etc/tor/torrc:

# Do not run as client
SocksPort 0 #Run Tor only as a relay and do not create a local SOCKS proxy
SocksPolicy reject *

# Define hidden service for SSH
HiddenServiceDir /var/lib/tor/sshservice/
HiddenServicePort 44674 #Redirect local SSH port to a nonstandard public port

ls -Z of /var/lib/tor:

[root@sagan tor]# ls -Z
-rw-------. toranon toranon system_u:object_r:tor_var_lib_t:s0 cached-certs
-rw-------. toranon toranon system_u:object_r:tor_var_lib_t:s0 cached-microdesc-consensus
-rw-------. toranon toranon unconfined_u:object_r:tor_var_lib_t:s0 cached-microdescs
-rw-------. toranon toranon unconfined_u:object_r:tor_var_lib_t:s0 cached-microdescs.new
-rw-------. toranon toranon unconfined_u:object_r:tor_var_lib_t:s0 lock
drwx------. toranon toranon system_u:object_r:tor_var_lib_t:s0 sshservice
-rw-------. toranon toranon unconfined_u:object_r:tor_var_lib_t:s0 state

Not sure what might be causing this issue, but I suspect it's something to do with the precise configuration of systemd. I have experimented with commenting and removing some of the lines in the default systemd tor.service file, but with no success.

Currently I am attempting to start tor using systemctl start tor using the default systemd tor.service file shipped with CentOS.

Any ideas? Help would be greatly appreciated.

  • You have to start TOR with service tor start. Then it runs as toranon and permissions are aligned.
    – Chloe
    Commented Mar 17, 2017 at 7:16

5 Answers 5


I just puzzled through this problem myself, no thanks to systemd's horrible lack of debugging ability.

It turns out that systemd was interfering in my case. It was allowing the toranon user to read /var/lib/tor/ but not its subdirectory /var/lib/tor/hidden_service on startup. Thus, if I started up tor as root using the same command it would work, but starting under systemd caused it to fail cryptically. The permissions on the directory were correct, which was all the more baffling.

The way I fixed the problem was to change my torrc file write the hidden service files to a directory that systemd allowed the process to write. That is, you may be able to change your line from:

HiddenServiceDir /var/lib/tor/sshservice/


HiddenServiceDir /var/lib/tor/

and everything may finally work.

The other option would probably be to tell systemd to allow the process to read the subdirectory by changing the systemd configuration file for tor.service, likely in:


And changing the ReadWriteDirectories option to include the subdirectory you're creating, possibly by adding a line:


Or adding that path as a space-separated list to one of the existing entries in that file. (It already has two different ReadWriteDirectories lines but I'm not sure if the second one works as no logs are getting written.) According to the documentation for systemd, the entry should be a space-separated list of absolute paths like:

ReadWriteDirectories=/var/lib/tor /var/lib/tor/sshservice /var/log/tor

Although I haven't tried making this more obscure change, silently hoping that systemd will die in a fire so we don't have to maintain a third set of files and permissions.

  • Thanks! Can confirm that the same solution you opted for also works for me. I had hoped to use the method that involved editing the systemd service file (as this current solution will only work for a single hidden service), however that didn't seem to work for me. I can verify that having multiple instances of ReadWriteDirectories vs concatenating them on a single line does not make any difference though - systemd seems to concatenate them itself (as seen when you run systemctl show tor after running a systemctl daemon-reload). I'll keep playing around and let you know if I succeed. Commented Nov 14, 2015 at 2:13

A few of the fixes that have been posted in answer to this question do work, but with variable rates of success.

One fix I have come across which works consistently is to load a few exceptions into SELinux.

Step 1

Create a tor-selinux-workaround.cil file with the following content:

(typeattributeset cil_gen_require tor_t) (allow tor_t self (capability (dac_override dac_read_search)))

Step 2

Import that file into SELinux with the following command:

sudo semodule -i tor-selinux-workaround.cil

This should work flawlessly for up-to-date Fedora and CentOS systems.

More Info

For a more complete explanation, see my post here: https://alexhaydock.co.uk/tech/fix-tor-onion-services-on-centos-fedora


If you want to be able to start and stop tor using systemctl, then the best course of action is to resist modifying the security configuration that's shipped by default.

There should be a file on your system located in the apparmor directory called system_tor, located here : /etc/apparmor.d/system_tor

If you look into this file you should see a list of directories that tor is already pre-configured to work with. Here's what my working and default version of the file contains:

# vim:syntax=apparmor
#include <tunables/global>

profile system_tor flags=(attach_disconnected) {
  #include <abstractions/tor>

  owner /var/lib/tor/** rwk,
  owner /var/lib/tor/ r,
  owner /var/log/tor/* w,

  # During startup, tor (as root) tries to open various things such as
  # directories via check_private_dir().  Let it.
  /var/lib/tor/** r,

  /{,var/}run/tor/ r,
  /{,var/}run/tor/control w,
  /{,var/}run/tor/socks w,
  /{,var/}run/tor/tor.pid w,
  /{,var/}run/tor/control.authcookie w,
  /{,var/}run/tor/control.authcookie.tmp rw,
  /{,var/}run/systemd/notify w,

  # Site-specific additions and overrides. See local/README for details.
  #include <local/system_tor>

If you look at the first directory path that shows up, you'll see owner /var/lib/tor/** rwk, Note the double astrix. This effectively says that the tor service is allowed to read and write to whatever folders and files are located inside /var/lib/tor

You should also see the path located in your tor.service, or depending on the version, your [email protected] file. Here's what the [email protected] looks like by default in my current working version:

Description=Anonymizing overlay network for TCP
After=network.target nss-lookup.target

ExecStartPre=/usr/bin/install -Z -m 02755 -o debian-tor -g debian-tor -d /run/tor
ExecStartPre=/usr/bin/tor --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc --RunAsDaemon 0 --verify-config
ExecStart=/usr/bin/tor --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc --RunAsDaemon 0
ExecReload=/bin/kill -HUP ${MAINPID}

# Hardening

With all of this in mind, what you want your torrc hidden service configurations to look like is this:

HiddenServiceDir /var/lib/tor/sshservice
HiddenServicePort 44674
HiddenServiceVersion 3

You will then need to pre-configure the directory so that tor can use it properly. This process would look something like this:

sudo mkdir /var/lib/tor/sshservice
sudo chown -R toranon:toranon /var/lib/tor/sshservice # some versions use debian-tor instead of toranon
sudo chmod 700 /var/lib/tor/sshservice

Before you're able to run tor using the systemctl command, you may have to first run it manually to generate the required hidden service files. This may be a bug on my particular instance. Do this like so:

sudo -u toranon tor

Once you do that, kill the tor process with ctrl+c or by using the kill command.

You should now be able to start and stop tor using either the systemctl command or the system command.


In my case, I had to add CAP_DAC_READ_SEARCH to the CapabilityBoundingSet of the systemd service:

/etc/systemd/system/multi-user.target.wants/[email protected]

@@ -30,7 +30,7 @@


(changing ReadWriteDirectories was not required)

  • /etc/centos-release: CentOS Linux release 7.2.1511 (Core)
  • systemctl --version: systemd 219
  • tor --version: Tor version
  • selinux: disabled

If selinux is enabled, tor still does not work! /var/log/audit/audit.log:

type=AVC msg=audit(1475960766.994:123): avc:  denied  { dac_override } for  pid=2317 comm="tor" capability=1  scontext=system_u:system_r:tor_t:s0 tcontext=system_u:system_r:tor_t:s0 tclass=capability
type=AVC msg=audit(1475960766.994:123): avc:  denied  { dac_read_search } for  pid=2317 comm="tor" capability=2  scontext=system_u:system_r:tor_t:s0 tcontext=system_u:system_r:tor_t:s0 tclass=capability

Follow https://bugzilla.redhat.com/show_bug.cgi?id=1292626 to fix that.

The above seems to be required only, if hidden services are used.

  • If you read carefully, you're advised to not use CAP_DAC_READ_SEARCH. It's far better to relax perms for the folder, and adding root to the allowed groups to access dirs.
    – m3nda
    Commented Apr 24, 2017 at 10:45

on Debian Jessie, this worked for me (I store tor hidden service information in /opt/tor)

edit /etc/tor/torrc by adding appropriate HiddenServiceDir and HiddenServicePort directives:

HiddenServiceDir /opt/tor/

HiddenServicePort 80

edit /lib/systemd/system/[email protected] , add this line at the end of file:


create directory and set ownership and permissions:

mkdir /opt/tor

chown debian-tor. /opt/tor

chmod go-rwx /opt/tor

reload service configuration:

systemctl daemon-reload

and start service:

systemctl start tor

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .