Windows service for scheduled FTPS backups. It mirrors a remote FTP folder to a local drive path nightly at 02:00 and keeps the five most recent timestamped snapshots.
- .NET SDK 10.0+
- Windows machine with access to the remote FTP server
- Local destination on a drive letter path (for example:
D:\Backups\SiteA)
- Build and publish the service:
dotnet publish .\BackupService\BackupService.csproj -c Release -o C:\Services\BackupService- Create the Windows service:
sc.exe create BackupService binPath= "C:\Services\BackupService\BackupService.exe"- (Optional) Set the service account if needed:
sc.exe config BackupService obj= ".\ServiceUser" password= "YourPassword"- Start the service:
sc.exe start BackupServiceEdit BackupService\appsettings.json (development) or provide a matching
appsettings.json alongside the published executable. The important
sections are BackupOptions and FileLogging.
Key settings:
BackupOptions:RunAt: local time for daily run (default02:00).BackupOptions:DefaultTimeoutMinutes: per-job timeout (default60).BackupOptions:HistoryCopies: number of snapshots kept (default5).BackupOptions:Backups: list of backup jobs.
Each backup job supports:
Name: friendly name for logs.Host,Port,Username,Password: FTP server credentials.RemotePath: remote folder to mirror.LocalPath: local drive folder to store the mirror and snapshots.Encryption:ExplicitorImplicit(defaultExplicit).Passive:truefor passive mode (defaulttrue).AllowInvalidCertificate: settrueto skip TLS validation.TimeoutMinutes: overrides the default timeout.HistoryCopies: overrides the default retention count.
Example:
{
"FileLogging": {
"Path": "logs\\backup.log",
"MinimumLevel": "Information"
},
"BackupOptions": {
"RunAt": "02:00",
"HistoryCopies": 5,
"DefaultTimeoutMinutes": 60,
"CurrentSubdirectoryName": "current",
"HistorySubdirectoryName": "_history",
"Backups": [
{
"Name": "SiteA",
"Host": "ftp.example.com",
"Port": 21,
"Username": "user",
"Password": "password",
"RemotePath": "/",
"LocalPath": "D:\\Backups\\SiteA",
"Encryption": "Explicit",
"Passive": true,
"AllowInvalidCertificate": false,
"TimeoutMinutes": 60,
"HistoryCopies": 5
}
]
}
}Passwords are stored in clear text in appsettings.json. For production
use, consider setting credentials in environment variables and leaving
the file values blank:
$env:BackupOptions__Backups__0__Username = "user"
$env:BackupOptions__Backups__0__Password = "password"- The service runs once per day at the configured time.
- Backups execute sequentially; a failure does not block the next job.
- Each job is cancelled if it exceeds its timeout.
- The remote path is mirrored into
LocalPath\current. - Snapshot copies are stored in
LocalPath\_history\yyyyMMdd_HHmmss. - Logs are written to the Windows Event Log and to the file path in
FileLogging:Path.
You can run the worker as a console app for quick testing:
dotnet run --project .\BackupService\BackupService.csprojPress Ctrl+C to stop it.
sc.exe stop BackupService
sc.exe delete BackupService- If the service cannot write logs, ensure the service account has write access to the log directory and backup destination.
- If TLS validation fails, set
AllowInvalidCertificatetotruefor the specific backup or install a trusted certificate on the machine. - If Event Log entries do not appear, run the service once with elevated permissions or pre-create the event source.