Audit website ownership, file permissions and writable directories on Linux
Use stat, namei and find to diagnose Linux website permissions, separate writable data from code and apply targeted changes instead of chmod 777.
Read the guideWeb hosting · Practical guide
Separate deployment access from account administration, preview rsync changes and verify a release without exposing credentials or deleting target data blindly.
Archive placement: July 2023

A designer or deployment process often needs to change one website, not administer your billing account, mailboxes and every other service. Separate identities and a deliberate file-transfer workflow reduce accidental changes and make access easier to remove. The important controls are the scope of the account, the destination path and the verification after transfer.
Use an individual or purpose-specific deployment account instead of sharing the primary Control Panel login. On a VPS, give that account ownership or group access to the intended release location without granting unrestricted sudo merely to upload files. On shared hosting, use the provider's supported account-scoping tools.
Define the exact site, access window and person responsible for removing the credential. If automated deployment is required, keep its key separate from an administrator's personal key. Consider what the account can read as well as what it can write: private configuration and unrelated sites may live beside the deployment directory.
umask 077
ssh-keygen -t ed25519 -a 64 \
-f ~/.ssh/site_deploy_ed25519 -C 'website-deployment'Protect the private key and install only its public key for the intended server account through an authorized setup process. Verify the server host-key fingerprint independently before the first transfer. SFTP runs over SSH; FTP with TLS is a separate protocol and must be explicitly supported and configured.
ssh -o IdentitiesOnly=yes -i ~/.ssh/site_deploy_ed25519 \
deploy@server.example.comConfirm the account identity and target directory in this session. A successful login does not prove that the account has only the intended privileges, so review the permissions and any authorized_keys restrictions as part of account setup.
rsync -av --dry-run --itemize-changes \
--exclude='.git/' --exclude='.env' \
-e 'ssh -o IdentitiesOnly=yes -i ~/.ssh/site_deploy_ed25519' \
./site/ deploy@server.example.com:/srv/www/example-app/releases/test/The trailing slash on ./site/ means transfer the directory's contents. Verify that both source and destination refer to the intended site. Review the itemized output for unexpected paths and file counts. The example excludes repository metadata and the environment file; prepare production configuration separately using a controlled process.
This example deliberately omits --delete. That option removes target entries absent from the source and can erase uploads or unrelated data if the path or application layout is wrong. If your deployment design needs deletion, establish exclusions, a tested backup and a reviewed dry run before adding it.
rsync -av --itemize-changes \
--exclude='.git/' --exclude='.env' \
-e 'ssh -o IdentitiesOnly=yes -i ~/.ssh/site_deploy_ed25519' \
./site/ deploy@server.example.com:/srv/www/example-app/releases/test/Check the transfer exit status and any permission errors. Avoid uploading directly over a live application if that can expose a half-updated codebase. A release-directory and cutover process, or an application-supported maintenance window, can separate file transfer from activation.
Do not transfer a private SSH key into the website tree. Keep configuration secrets, SQL exports and deployment archives outside publicly served paths. An archive containing the whole account can carry far more access than the recipient needs for a website change.
Check the runtime requirements, file ownership and writable directories before switching traffic. Verify a representative URL and application workflow, then inspect logs. A byte-for-byte file transfer does not update a database schema, install dependencies or confirm that an application can connect to its services.
curl --fail --show-error --silent \
--connect-timeout 5 --max-time 15 \
-o /dev/null -w 'status=%{http_code} total=%{time_total}s
' https://example.com/If the release fails, return to the previous known-good release or follow the application's rollback procedure. Coordinate database rollback separately; replacing old code can be unsafe after an incompatible schema change. Keep a written record of the deployed release and the tests that passed.
Limited access is most useful when it remains limited over time. A temporary upload account left active for years becomes part of the attack surface even if the original project is finished.
Copyright 2026 © Plenty Host Inc. - All Rights Reserved.
By using our services, you agree to our Terms & Conditions and Privacy Policy.
We Accept: 