Django assigns permissions to any user-submitted files it saves. If you don't explicitly set what these are, it uses an operating system default - which, in most cases, is
0600. If you're unfamiliar with unix-style file permissions, that means the following:
0: The first zero means that this number is an octal, or base 8, number.
6: The user that created the file (whatever the Django app is running as, most likely) can read and write to the file
0: The group that this file belongs to has no permissions
0: Everyone else also has no permissions
That's what I got on my Debian server, and it did not work with the permission scheme I have set up. My backup user is part of the group that these files are assigned to, which means they couldn't be backed up.
Setting octal file permissions
If you want to change the default, you can do so with the
FILE_UPLOAD_PERMISSIONS setting in your
# Assigns read+write to user, and read only to group FILE_UPLOAD_PERMISSIONS = 0o640 # Python 2 compatible version FILE_UPLOAD_PERMISSIONS = 0640
I'm fine with using the old-style octal format, but Python also supplies a better (albeit lightly documented) option.
stat module and bitwise OR
Django's file permissions are governed by python's
os.chmod syntax, which itself references the
stat module. I'll save you the recursive documentation dive, and show you some of the basics.
stat module comes with consonants that represent different permissions. Because we're dealing with file uploads, I'll ignore the ones that won't apply.
- User permissions:
S_IRUSRfor read permission,
S_IWUSRfor write permission,
S_IXUSRfor execute permission, and
S_IRWXUfor all three
- Group permissions:
S_IRGRPfor read permission,
S_IWGRPfor write permission,
S_IXGRPfor execute permission, and
S_IRWXGfor all three
- Other/everyone permissions:
S_IROTHfor read permission,
S_IWOTHfor write permission,
S_IXOTHfor execute permission, and
S_IRWXOfor all three
You combine these constants with a bitwise OR operator, which is a pipe (
| )character, that combines them together as one binary value. That changes my previous example to a much clearer, less cryptic piece of code.
# Assigns read+write to user, and read only to group import stat FILE_UPLOAD_PERMISSIONS = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP
That makes much more sense for my web server setup.
I would also add that you shouldn't ever add execute permission to files uploaded by users - that would have some very serious security implications!
Tags: python django linux server security