Skip to content

Commit 55b1089

Browse files
Add deployment documentation (#34)
1 parent 48a2dbc commit 55b1089

File tree

8 files changed

+348
-100
lines changed

8 files changed

+348
-100
lines changed

README.md

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,15 @@
2828

2929
## Installation
3030

31-
### Download
32-
1. Visit our [official website](https://www.bytesyncapp.com).
31+
### Download the Precompiled Client
32+
1. Visit our [official website](https://www.bytesyncapp.com#download).
3333
2. Download the right version for your operating system.
3434

35-
### Build from Source (Optional)
36-
To build ByteSync from source:
37-
```bash
38-
git clone https://github.com/POW-Software/ByteSync.git
39-
cd ByteSync
40-
dotnet build
41-
```
35+
### Building from Source
36+
If you prefer to build ByteSync from source or want to deploy specific components:
37+
38+
- For **client-side deployment** steps, refer to [docs/client-deployment.md](docs/client-deployment.md).
39+
- For **server-side deployment** steps, refer to [docs/server-deployment.md](docs/server-deployment.md).
4240

4341
---
4442

docs/client-deployment.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# ByteSync Client Deployment Documentation
2+
3+
## Technology and Requirements
4+
5+
These projects are written in **C#** and target a specific version of **.NET**. You can find the exact .NET version required by checking the `.csproj` file of the **ByteSync.Client** project. You must have the appropriate .NET SDK installed to build and deploy the solution.
6+
7+
## Cloning and Building from Source
8+
9+
1. **Clone the Repository**:
10+
11+
```bash
12+
git clone https://github.com/POW-Software/ByteSync.git
13+
```
14+
15+
Navigate to the `ByteSync.Client` folder if needed.
16+
17+
2. **Open the C# Project**:
18+
19+
- Open the `.sln` (solution) file in Visual Studio or Visual Studio Code.
20+
- Verify that the .NET version specified in the `.csproj` is installed on your system.
21+
22+
3. **Create `local.settings.json`** at the project root. Example content:
23+
24+
```json
25+
{
26+
"LocalDebugUrl": "",
27+
"DevelopmentUrl": "",
28+
"StagingUrl": "",
29+
"ProductionUrl": "",
30+
"UpdatesDefinitionUrl": ""
31+
}
32+
```
33+
34+
Fill in any relevant URLs or other settings your environment requires.
35+
36+
4. **Build the Project**:
37+
38+
- Use the command line:
39+
```bash
40+
dotnet build
41+
```
42+
- Or build directly through Visual Studio / VS Code.
43+
44+
5. **Run the Client**:
45+
46+
```bash
47+
dotnet run
48+
```
49+

docs/server-deployment.md

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
# ByteSync Server Deployment Guide
2+
3+
This guide provides instructions for deploying the **ByteSync Server** components on Azure, including the **Azure Function**, **Azure Cosmos DB**, and **Redis**.
4+
5+
---
6+
7+
## Technology and Requirements
8+
9+
These projects are written in **C#** and target a specific version of **.NET**. You can find the exact .NET version required by checking the corresponding `.csproj` files. You must have the appropriate .NET SDK installed to build and deploy the solution.
10+
11+
## Components to Deploy
12+
13+
1. **Azure Function**
14+
15+
- **Windows-only** deployment (currently not tested on Linux).
16+
- This is the main entry point for ByteSync’s server-side functionality, handling requests and orchestrating other services.
17+
- Deployed from the `ByteSync.Functions` project.
18+
- You can deploy via the Azure Portal or from your local machine (Visual Studio / CLI). Make sure to configure your connection strings and secrets.
19+
20+
2. **Azure Cosmos DB**
21+
22+
- A globally distributed, multi-model database.
23+
- Stores persistent data for ByteSync (such as metadata, user data, or other domain-related information).
24+
- The necessary containers may be auto-created on startup if configured properly.
25+
26+
3. **Redis**
27+
28+
- An in-memory data store used for caching and rapid data retrieval.
29+
- Useful for session management, real-time messaging, or other scenarios where speed is critical.
30+
- You can specify a prefix (`Prefix`) in configuration to logically group or namespace your cache keys.
31+
32+
---
33+
34+
## Projects Requiring Configuration
35+
36+
The following projects require configuration to function properly:
37+
38+
- **ByteSync.Functions**
39+
- **ByteSync.Functions.IntegrationTests**
40+
- **ByteSync.ServerCommon.Tests**
41+
42+
You can store and manage application settings for these projects in several ways:
43+
44+
- **Azure App Configuration:** A dedicated service for hosting and managing settings in Azure. Only for the **ByteSync.Functions** project.
45+
- **local.settings.json (for local development):** Typically used for local debugging and testing.
46+
- **.NET User Secrets:** A secure way to store local secrets without committing them to source control.
47+
48+
---
49+
50+
## Required Configuration Properties
51+
52+
Below is the JSON structure indicating which properties must be set. In particular, **`AppSettings:Secret`** should be a unique random string (for example, generated via `openssl rand -base64 32`) to secure tokens or other sensitive operations:
53+
54+
```json
55+
{
56+
"Redis": {
57+
"ConnectionString": "",
58+
"Prefix": ""
59+
},
60+
"BlobStorage": {
61+
"Endpoint": "",
62+
"Container": "",
63+
"AccountKey": "",
64+
"AccountName": ""
65+
},
66+
"SignalR": {
67+
"ConnectionString": ""
68+
},
69+
"CosmosDb": {
70+
"ConnectionString": "",
71+
"DatabaseName": ""
72+
},
73+
"AppSettings": {
74+
"Secret": "YOUR_UNIQUE_RANDOM_SEED"
75+
}
76+
}
77+
```
78+
79+
---
80+
81+
## Configuration Options
82+
83+
### 1. Using `local.settings.json`
84+
85+
`local.settings.json` is typically used for local development. An example might look like this:
86+
87+
```json
88+
{
89+
"IsEncrypted": false,
90+
"Values": {
91+
"Redis:ConnectionString": "<your-redis-connection-string>",
92+
"Redis:Prefix": "<your-redis-prefix>",
93+
"BlobStorage:Endpoint": "<your-blob-endpoint>",
94+
"BlobStorage:Container": "<your-container-name>",
95+
"BlobStorage:AccountKey": "<your-account-key>",
96+
"BlobStorage:AccountName": "<your-account-name>",
97+
"SignalR:ConnectionString": "<your-signalr-connection-string>",
98+
"CosmosDb:ConnectionString": "<your-cosmosdb-connection-string>",
99+
"CosmosDb:DatabaseName": "<your-database-name>",
100+
"AppSettings:Secret": "YOUR_UNIQUE_RANDOM_SEED"
101+
}
102+
}
103+
```
104+
105+
> **Important:** `local.settings.json` is automatically excluded by default in `.gitignore` so it won't be committed to source control. Ensure you keep it that way. If you see it in your changes, verify that the ignore rules haven't been modified.
106+
107+
---
108+
109+
### 2. Using .NET User Secrets
110+
111+
For secure storage of secrets during local development, you can use **[.NET Secret Manager](https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets)**.
112+
113+
Below is an example of how to set these secrets for **ByteSync.Functions**:
114+
115+
```bash
116+
# Navigate to the ByteSync.Functions project directory
117+
cd ByteSync.Functions
118+
119+
# Set each secret
120+
# Redis
121+
dotnet user-secrets set "Redis:ConnectionString" "<your-redis-connection-string>"
122+
dotnet user-secrets set "Redis:Prefix" "<your-redis-prefix>"
123+
124+
# Blob Storage
125+
dotnet user-secrets set "BlobStorage:Endpoint" "<your-blob-endpoint>"
126+
dotnet user-secrets set "BlobStorage:Container" "<your-container-name>"
127+
dotnet user-secrets set "BlobStorage:AccountKey" "<your-account-key>"
128+
dotnet user-secrets set "BlobStorage:AccountName" "<your-account-name>"
129+
130+
# SignalR
131+
dotnet user-secrets set "SignalR:ConnectionString" "<your-signalr-connection-string>"
132+
133+
# Cosmos DB
134+
dotnet user-secrets set "CosmosDb:ConnectionString" "<your-cosmosdb-connection-string>"
135+
dotnet user-secrets set "CosmosDb:DatabaseName" "<your-database-name>"
136+
137+
# App Settings
138+
dotnet user-secrets set "AppSettings:Secret" "YOUR_UNIQUE_RANDOM_SEED"
139+
```
140+
141+
Repeat these steps for **ByteSync.Functions.IntegrationTests** and **ByteSync.ServerCommon.Tests**, navigating to each project's directory and setting the same secrets.
142+
143+
---
144+
145+
### 3. Using Azure App Configuration
146+
147+
1. **Create an Azure App Configuration** resource via the Azure Portal.
148+
2. **Add** the keys listed above (e.g., `Redis:ConnectionString`, `BlobStorage:Endpoint`, etc.).
149+
3. **Link** your Azure Function to the App Configuration resource.
150+
4. Ensure your Azure Function is configured to pull values from Azure App Configuration.
151+
152+
---
153+
154+
## Final Steps
155+
156+
1. **Deploy** your Azure Function (Windows) to Azure.
157+
2. **Create** your Cosmos DB and Redis resources.
158+
3. **Verify** that your secrets and connection strings are correctly configured (via local or remote settings).
159+
4. **Test** the deployment to confirm everything is working.
160+
161+
---
162+
163+
## Best Practices
164+
165+
- **Security:** Never commit secrets (e.g. `local.settings.json`) to source control.
166+
- **Production Secrets:** For production, prefer environment variables, Azure Key Vault, or Azure App Configuration.
167+
- **Monitoring:** Enable Azure monitoring for real-time logs and alerts.
168+
169+
For issues or questions, please open an issue on the [ByteSync GitHub repository](https://github.com/POW-Software/ByteSync).
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using Azure.Identity;
2+
using ByteSync.Common.Helpers;
3+
using Microsoft.Extensions.Configuration;
4+
using Microsoft.Extensions.Configuration.AzureAppConfiguration;
5+
using Microsoft.Extensions.Hosting;
6+
7+
namespace ByteSync.Functions.Helpers;
8+
9+
public static class AzureAppConfigurationLoader
10+
{
11+
public static void AddAzureAppConfiguration(this IConfigurationBuilder builder, HostBuilderContext hostingContext, IConfiguration configuration)
12+
{
13+
var azureAppConfigurationUrl = configuration.GetValue<string>("AzureAppConfigurationUrl");
14+
15+
if (azureAppConfigurationUrl.IsNullOrEmpty())
16+
{
17+
return;
18+
}
19+
20+
Console.WriteLine("Loading configuration from Azure App Configuration...");
21+
22+
builder.AddAzureAppConfiguration(options =>
23+
{
24+
var credentials = new DefaultAzureCredential(new DefaultAzureCredentialOptions
25+
{
26+
ExcludeAzureDeveloperCliCredential = true,
27+
ExcludeEnvironmentCredential = true,
28+
ExcludeAzurePowerShellCredential = true,
29+
ExcludeInteractiveBrowserCredential = true,
30+
ExcludeSharedTokenCacheCredential = true,
31+
});
32+
33+
options.Connect(new Uri(azureAppConfigurationUrl!), credentials)
34+
.ConfigureStartupOptions(startupOptions =>
35+
{
36+
startupOptions.Timeout = TimeSpan.FromSeconds(240);
37+
})
38+
// Load configuration values with no label
39+
.Select(KeyFilter.Any, LabelFilter.Null)
40+
// Override with any configuration values specific to current hosting env
41+
.Select(KeyFilter.Any, hostingContext.HostingEnvironment.EnvironmentName);
42+
43+
options.ConfigureKeyVault(kv => kv.SetCredential(credentials));
44+
});
45+
}
46+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using System.Reflection;
2+
using Autofac;
3+
using ByteSync.Common.Interfaces.Hub;
4+
using ByteSync.ServerCommon.Hubs;
5+
using ByteSync.ServerCommon.Interfaces.Factories;
6+
using ByteSync.ServerCommon.Interfaces.Repositories;
7+
using ByteSync.ServerCommon.Storage;
8+
using Microsoft.Azure.SignalR.Management;
9+
10+
namespace ByteSync.Functions.Helpers;
11+
12+
public static class DependencyInjectionLoader
13+
{
14+
public static void LoadDependencyInjection(this ContainerBuilder builder)
15+
{
16+
var executingAssembly = Assembly.GetExecutingAssembly();
17+
18+
builder.RegisterAssemblyTypes(executingAssembly)
19+
.Where(t => t.Name.EndsWith("Service"))
20+
.InstancePerLifetimeScope()
21+
.AsImplementedInterfaces();
22+
23+
// ByteSync.ServerCommon
24+
executingAssembly = typeof(IClientsRepository).Assembly;
25+
26+
builder.RegisterAssemblyTypes(executingAssembly)
27+
.Where(t => t.Name.EndsWith("Repository"))
28+
.InstancePerLifetimeScope()
29+
.AsImplementedInterfaces();
30+
31+
builder.RegisterAssemblyTypes(executingAssembly)
32+
.Where(t => t.Name.EndsWith("Service"))
33+
.InstancePerLifetimeScope()
34+
.AsImplementedInterfaces();
35+
36+
builder.RegisterAssemblyTypes(executingAssembly)
37+
.Where(t => t.Name.EndsWith("Factory"))
38+
.InstancePerLifetimeScope()
39+
.AsImplementedInterfaces();
40+
41+
builder.RegisterAssemblyTypes(executingAssembly)
42+
.Where(t => t.Name.EndsWith("Loader"))
43+
.InstancePerLifetimeScope()
44+
.AsImplementedInterfaces();
45+
46+
builder.RegisterAssemblyTypes(executingAssembly)
47+
.Where(t => t.Name.EndsWith("Mapper"))
48+
.InstancePerLifetimeScope()
49+
.AsImplementedInterfaces();
50+
51+
builder.RegisterType<ByteSyncClientCaller>()
52+
.InstancePerLifetimeScope()
53+
.AsImplementedInterfaces();
54+
55+
builder.RegisterType<BlobContainerProvider>()
56+
.InstancePerLifetimeScope()
57+
.AsImplementedInterfaces();
58+
59+
builder.Register(c => {
60+
var factory = c.Resolve<IHubContextFactory>();
61+
return factory.CreateHubContext();
62+
}).As<ServiceHubContext<IHubByteSyncPush>>().SingleInstance().AsImplementedInterfaces();
63+
}
64+
}

0 commit comments

Comments
 (0)