RE:NODE

SFTP permission denied: connected but cannot edit files

By RE:NODE Team
15 min read


If your SFTP client logs in, lists the folders and downloads files without complaint, but every save, upload or delete ends in Permission denied, the login is not the problem. Authentication worked. What failed is the next check: the operating system (or the panel's SFTP service) deciding whether the user you logged in as may write to that particular file, or to the folder that contains it. On a machine you run yourself the cause is nearly always ownership - the files belong to the service user or to root, and you logged in as someone else. On a game panel the cause is nearly always a panel permission, a protected file, or a full disk. The fix is never chmod 777.

This post works through the causes in the order they actually turn up, with the command that confirms each one and the fix that does not create a new problem. File modes and the executable bit are covered in depth in game server file permissions and ownership; here the focus is the specific situation of being connected and still unable to write.

Read access works, write access does not: why#

SFTP is not a separate permission system. On an ordinary Linux server, OpenSSH's sftp-server (or internal-sftp) runs as the user you logged in as, and every file operation is an ordinary system call made as that user. If alice cannot write a file from a shell, alice cannot write it over SFTP either. The SFTP client is just reporting what the kernel said.

Reading needs much less than writing. To download server.properties you need r on the file and x on every directory above it. To change it you need w on the file. To upload a new file, delete one or rename one, you need w and x on the directory, regardless of the file's own mode. That asymmetry is why "I can see everything but change nothing" is such a common report: the default mode for files is 644 and for directories 755, which gives everyone except the owner exactly that - read, list, download, nothing else.

First, make sure the error is a write error and not a login error. These are different problems:

code
Permission denied (publickey,password).          <- login failed, see SSH keysError: /srv/game/server.properties: open for write: permission deniedremote open("/srv/game/start.sh"): Permission deniedCouldn't open for writing

The first line means you never got in, and SSH permission denied (publickey) is the post for that. Everything below is about the other three, which all mean the same thing: logged in, refused on one file or one folder. The exact wording depends on the client; FileZilla says open for write: permission denied, the OpenSSH sftp client says remote open(...) or dest open, and editor plugins tend to say they could not open the file for writing.

Who owns the file, and who are you#

Two commands answer almost every case. Over SSH, or from the sftp prompt, look at the file and its folder:

bash
$ ls -la /srv/game/drwxr-xr-x  5 steam steam 4096 Oct 14 20:10 .-rw-r--r--  1 steam steam 1843 Oct 14 20:11 server.properties-rw-r--r--  1 root  root   612 Oct 12 09:02 mods.json$ iduid=1001(alice) gid=1001(alice) groups=1001(alice)

Read it as a sentence. The folder belongs to steam and only steam may write in it. server.properties belongs to steam and only steam may change it. mods.json belongs to root, so not even steam may change it. And you are alice, who is neither, so the only bits that apply to you are the last three: r-x on the folder, r-- on the files. Read-only, exactly as observed.

Graphical clients show the same columns. In FileZilla the remote pane has Permissions and Owner/Group columns; in WinSCP they are in the remote panel and in a file's Properties. If the owner column shows a number instead of a name (988, 1000), the client simply has no name for that id - the ownership is still real.

The table below covers what you need for each operation. Note how often the directory matters more than the file:

You want toOn the fileOn the folder
Downloadrx (and r to list it)
Edit and save in placewx
Upload a new file-w and x
Delete or renamenothingw and x
Save via a temporary file-w and x

The last row is where editors trip people up, and it gets its own section below.

Files created by a service or by root#

On a VDS or home server, the usual story goes like this. A game, a web app or a bot runs as a dedicated service user - steam, www-data, minecraft. You log in over SFTP as your own user to edit its config. Your user can read everything (the files are 644) and write nothing. Or you did fix it once, and it came back, because the service keeps creating new files with its own owner and a 022 umask. Or someone ran an update with sudo, and now a handful of files belong to root and even the service cannot change them.

There are three sensible fixes, and which one is right depends on who should own the data.

Log in as the service user. The simplest option when one person administers the server. Give the service user an SSH key (not a password) and connect as it. Everything you upload then has the right owner from the start. This is fine for a game server user; do not do it for www-data or another account the system shares between services.

Share a group. When a person and a service both need to write, put them in a common group and make the tree group-writable:

bash
# a group for everyone who edits this server$ sudo groupadd gameadmins$ sudo usermod -aG gameadmins alice$ sudo usermod -aG gameadmins steam# hand the tree to the service user and the shared group$ sudo chown -R steam:gameadmins /srv/game$ sudo chmod -R g+rwX /srv/game# new files inside inherit the group, not the creator's own group$ sudo find /srv/game -type d -exec chmod g+s {} +

The capital X in g+rwX adds execute only to directories and to files that already had it, so it does not make every config executable. The g+s (setgid) bit on directories means anything created inside belongs to gameadmins rather than to whoever made it. Group membership is read at login, so alice must disconnect and reconnect before it takes effect - a step that wastes a surprising amount of time.

Setgid fixes the group, not the mode. If the service still creates files as 644 they will be in the right group but not group-writable. Set the service's umask to 002: for a systemd unit that is UMask=0002 in the [Service] section, followed by systemctl daemon-reload and a restart. For files you upload, OpenSSH lets you set the umask of the SFTP session itself with ForceCommand internal-sftp -u 0002 or Subsystem sftp internal-sftp -u 0002 in sshd_config.

Use ACLs when the group model gets awkward (several services, one tree each). A default ACL on a directory applies to everything created in it later:

bash
$ sudo setfacl -R -m u:alice:rwX /srv/game$ sudo setfacl -R -d -m u:alice:rwX /srv/game$ getfacl /srv/game/server.properties

ACLs show up as a + at the end of the mode in ls -l (-rw-rw-r--+), and many SFTP clients do not display them at all, which is worth remembering when the visible mode seems to contradict what actually happens.

What not to do: chmod -R 777. It makes every file writable by every account and every compromised process on the machine, and it does not survive the service creating its next file anyway. The other bad fix, running the service as root so it can "write anything", is covered in the ownership section of the permissions post, and the short version is that a vulnerable plugin then owns the whole machine. Multiple game servers on one VDS describes the one-user-per-server layout that makes all of this predictable.

Chroot SFTP: the folder you land in is not yours#

Chrooted SFTP is common on shared and hand-built hosting: the user is locked into one directory and cannot see the rest of the system. The usual configuration looks like this:

/etc/ssh/sshd_config
Match User alice    ChrootDirectory /srv/sftp/alice    ForceCommand internal-sftp    AllowTcpForwarding no    X11Forwarding no

OpenSSH insists that the chroot directory and every directory above it are owned by root and not writable by any other user or group. If they are, the login fails and the server's auth log says bad ownership or modes for chroot directory. The consequence is the classic chroot complaint: the user logs in, lands in /, and cannot upload anything, because / inside the jail is a root-owned directory they are not allowed to write to - by design.

The fix is a writable subdirectory inside the jail:

bash
$ sudo chown root:root /srv/sftp/alice$ sudo chmod 755 /srv/sftp/alice$ sudo mkdir /srv/sftp/alice/upload$ sudo chown alice:alice /srv/sftp/alice/upload

Users then write into /upload. If the files need to reach the real application folder, use a bind mount rather than a symlink - a symlink pointing outside the jail resolves inside it and goes nowhere.

Read-only mounts, full disks and immutable files#

Sometimes the mode is fine, the owner is fine, and writing still fails. Three causes sit below permissions entirely.

A read-only filesystem. The error is Read-only file system (EROFS), though some SFTP clients flatten it into a generic failure or even permission denied. Check the mount options:

bash
$ findmnt -no OPTIONS --target /srv/gamero,relatime

A volume can be mounted ro on purpose (a network share, an ISO, a container volume mounted read-only), but a filesystem that was writable yesterday and is ro today usually means the kernel remounted it after detecting a disk error. That is a hardware or host problem, not a settings problem; look at dmesg and stop writing to it until it is understood.

A full disk, or no inodes left. Writes fail when there is no space, and many clients report it badly - a truncated upload, a zero-byte file after saving, or a vague error instead of No space left on device. Check both bytes and inodes:

bash
$ df -h /srv/game$ df -i /srv/game

There is a twist on ext4: about 5% of blocks are reserved for root by default. At 96% full, a root process can still write while your user cannot, which looks exactly like a permissions problem. Game server disk space full covers finding what filled it.

An immutable file. chattr +i makes a file unchangeable even by root, and the error is Operation not permitted. Some admins use it to stop a game rewriting a config, then forget. Check and clear it from a shell:

bash
$ lsattr /srv/game/server.properties----i---------e------- /srv/game/server.properties$ sudo chattr -i /srv/game/server.properties

On distributions with SELinux enforcing (Fedora, RHEL and its rebuilds) there is one more layer: a file with the wrong security context can be refused even when the mode allows it. ls -Z shows the context, and files moved rather than copied into place are the usual culprits.

Editors that save through a temporary file#

A common and confusing case: you can overwrite a file by uploading it, but saving it from your editor fails, or the reverse. The reason is that "saving" is not one operation. Many tools write a new file next to the original and then rename it over the top, so that a dropped connection cannot leave a half-written config. That needs w on the directory. If you have write access to the file but not to its folder, an in-place write succeeds and a temp-file save fails.

WinSCP does this for uploads by default: a file is transferred as name.filepart and renamed when complete. The option lives under Preferences, Transfer, Endurance, as "Enable transfer resume/transfer to temporary filename". Setting it to Disable makes WinSCP write straight into the target file, which works when only the file is writable. WinSCP also tries to set the permissions and timestamp after an upload; when it may write the file but not change its attributes, it reports that the upload succeeded but setting permissions or timestamp failed. The upload did work. The transfer settings have an "Ignore permission errors" option, or untick "Set permissions" and "Preserve timestamp" for that connection.

FileZilla writes in place, so the temp-file problem rarely applies; its "View/Edit" downloads a local copy and uploads it again when you save, which is an ordinary upload with ordinary rules. If FileZilla shows open for write: permission denied, the file or its folder really is not writable by your user.

Editor extensions and other tools vary. VS Code SFTP extensions, Notepad++ plugins and sshfs mounts each have their own strategy, and some also try to preserve the original file's mode on save. If one tool works and another does not on the same file, assume a temp-file or attribute difference before assuming the server changed.

There is a second trap in the other direction: a client set to apply fixed permissions on upload can quietly change modes. If a script loses its executable bit every time you upload it, look at the client's upload permission settings rather than at the server.

On a Pterodactyl-style game panel#

Panels built on Pterodactyl and Wings do not use OpenSSH for file access. Wings runs its own SFTP service, the username has the server's short id appended (alice.1a2b3c4d), the port is usually 2022 rather than 22, and there is no shell behind it. Every file belongs to the single unprivileged user that the server's container runs as - the one shown as container in listings - and anything you upload is given that owner automatically. So the root-made-file problem and the "service user vs my user" problem do not happen here. chown is not available and is not needed; chmod works for setting modes such as 755 on a script.

When writing fails on a panel, the causes are different:

SymptomLikely cause
Can list and download, cannot upload anythingYour subuser account lacks create or update file permission
Can create new files, cannot overwrite existing onesCreate granted, update not
Cannot delete or renameDelete permission missing
One specific file always refusedThe server's egg lists it in its file denylist
Uploads fail or truncate after working beforeDisk limit reached
Login itself refusedSFTP permission missing, or wrong username format

Upstream Pterodactyl splits file access into separate permissions - reading, reading contents, creating, updating, deleting, archiving and SFTP itself - and the SFTP service checks the same permissions as the browser file manager. A subuser given read and SFTP access but not update gets exactly the "connected but cannot edit" experience. The owner of the server fixes it by editing that person's permissions, not by changing anything in the files. Subusers and least privilege covers what to grant to whom.

The egg's file denylist is the other panel-specific cause. An egg author can mark files the server's users may not touch (often a licence file or a start script the host manages), and the SFTP service refuses them with a permission error even for the server owner. If exactly one file is always refused while its neighbours are fine, that is the first thing to suspect. Pterodactyl eggs for game servers explains what an egg controls.

On RE:NODE, SFTP is available on every server with credentials issued per server rather than per account, and the connection details are on the server in the panel. Access for other people goes through roles, teams and grants with granular file permissions, so "files only, no delete" is a real setting. When the server's disk figure hits its limit, writes stop; the console graphs show disk against the limit, which is the quickest way to rule that cause in or out. The files guide walks through the file manager and SFTP side by side, and SFTP and the file manager covers clients, scripted transfers and the files a running server holds open.

A checklist that finds it in five minutes#

Work down this list and stop at the first thing that is wrong:

  1. Is it a login error? Permission denied (publickey,password) means authentication, not files.
  2. Is it every file or one file? Everything refused points at your account, the mount or the disk. One file points at that file's owner, mode, immutable flag or a panel denylist.
  3. Who are you, and who owns it? id, then ls -la on the file and its folder. Compare the owner, group and the bits that apply to you.
  4. Is the folder writable? New files, deletes, renames and temp-file saves all need w on the directory.
  5. Is the disk full or read-only? df -h, df -i, findmnt. On a panel, the disk graph.
  6. Is the file immutable? lsattr.
  7. Does another client behave differently? If yes, look at temp-file uploads and attribute settings in the failing one.
  8. On a panel, what can your account do? Ask the owner to check your file permissions.

Each step is a single command or a single screen, and the order matters: it moves from the cheap, common causes to the rare ones.

FAQ#

Why can I download over SFTP but not upload?

Downloading needs read permission on the file; uploading needs write permission on the target folder. Default modes (644 for files, 755 for folders) give read to everyone and write only to the owner. If you log in as a different user from the one that owns the folder, you get exactly this. Log in as the owner, or share a group with it.

Will chmod 777 fix SFTP permission denied?

It often hides the symptom and always creates a bigger problem. Every user and process on the machine can then rewrite those files, and new files created by the service still arrive with their normal mode, so the problem returns. A shared group with setgid folders and a 002 umask solves it properly.

Why does WinSCP say the upload succeeded but setting permissions failed?

You may write the file but not change its attributes, usually because you are not its owner. The content was uploaded. Turn on "Ignore permission errors" in the transfer settings, or stop WinSCP setting permissions and timestamps on upload for that site.

I can't upload to the root folder after logging in to a chrooted account. Is it broken?

No. OpenSSH requires the chroot directory to be owned by root and not writable by the user, so the top level is read-only by design. Your administrator should create a subdirectory owned by your user inside the jail, and you upload there.

Why can I edit some files on my game panel but not others?

Either your subuser account has some file permissions and not others (create without update, for example), or the file is on the egg's denylist. Ownership is not the reason on a Pterodactyl-based panel, because every file in the server's folder belongs to the same container user.

Can a full disk cause permission denied?

Not literally, but many SFTP clients report a failed write vaguely, and on ext4 the blocks reserved for root mean a nearly full disk refuses ordinary users before it refuses root. Check df -h and df -i before changing any permissions.