Installation Guide
Complete step-by-step guide to install and configure Semantico in your ASP.NET Core application. This guide is based on the actual SampleProject implementation.
Prerequisites
Before you begin, ensure you have:
- .NET 9.0 SDK or later
- PostgreSQL 12+ or SQL Server 2019+ for Semantico metadata database
- Visual Studio 2022, Rider, or VS Code with C# support
- Job scheduler (Hangfire recommended, but Quartz.NET or custom implementations work)
Step 1: Install NuGet Packages
For PostgreSQL (Recommended)
# Core Semantico packages
dotnet add package Semantico.Core.PostgreSql
dotnet add package Semantico.UI.AspNet
# Job scheduler (Hangfire example)
dotnet add package Hangfire.AspNetCore
dotnet add package Hangfire.PostgreSql
For SQL Server
# Core Semantico packages
dotnet add package Semantico.Core.SqlServer
dotnet add package Semantico.UI.AspNet
# Job scheduler (Hangfire example)
dotnet add package Hangfire.AspNetCore
dotnet add package Hangfire.SqlServer
The provider you choose is for Semantico’s metadata database. You can still query PostgreSQL, SQL Server, and MySQL databases for monitoring regardless of which provider you choose.
Step 2: Generate Encryption Key
Semantico requires an encryption key for securing sensitive data like connection strings.
openssl rand -base64 32
Example output:
RO3H+z0xI28nYdTK5VIlYP4NYrrlgvy5Q0tjQBI7Fhk=
Save this key - you’ll need it in the next step.
Step 3: Configure appsettings.json
Add connection strings and Semantico configuration:
{
"ConnectionStrings": {
"SemanticoContext": "Host=localhost;Database=semantico;Username=postgres;Password=yourpassword"
},
"Semantico": {
"EncryptionKey": "RO3H+z0xI28nYdTK5VIlYP4NYrrlgvy5Q0tjQBI7Fhk="
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.EntityFrameworkCore.Database": "Warning"
}
}
}
Optional: Enable AI Features (Experimental)
⚠️ AI features are experimental. Add LLM configuration only if you plan to use AI-powered documentation or alert generation:
{
"Semantico": {
"EncryptionKey": "your-generated-key",
"LLM": {
"Provider": "OpenAI",
"ApiKey": "sk-your-openai-key",
"Model": "gpt-4o",
"Limits": {
"MaxConcurrentRequests": 5,
"RequestsPerMinute": 60,
"MaxTokensPerRequest": 4000
}
}
}
}
Supported Providers:
OpenAI- gpt-4o (recommended)Anthropic- claude-3-5-sonnet-20241022 (recommended)AzureOpenAI- Latest models only
Step 4: Create Job Scheduler Implementation
Create a class that implements ISemanticoScheduler. This example uses Hangfire (from SampleProject):
Create file: Services/SemanticoScheduler.cs
using Hangfire;
using Semantico.Core.Worker;
namespace YourProject.Services;
/// <summary>
/// Hangfire implementation of Semantico scheduler
/// </summary>
public class SemanticoScheduler : ISemanticoScheduler
{
private readonly IRecurringJobManager _recurringJobManager;
public SemanticoScheduler(IRecurringJobManager recurringJobManager)
{
_recurringJobManager = recurringJobManager;
}
public void AddOrUpdate(int subscriptionId, string subscriptionName, string cron)
{
_recurringJobManager.AddOrUpdate<IJobService>(
CompileSubscriptionJobKey(subscriptionId, subscriptionName),
x => x.ExecuteQuery(subscriptionId),
cron);
}
public void Remove(int subscriptionId, string subscriptionName)
{
_recurringJobManager.RemoveIfExists(
CompileSubscriptionJobKey(subscriptionId, subscriptionName));
}
private static string CompileSubscriptionJobKey(int subscriptionId, string subscriptionName)
{
return $"{subscriptionId} - {subscriptionName}";
}
}
If you prefer Quartz.NET or a custom scheduler, implement the same
ISemanticoSchedulerinterface with your chosen scheduler. See Alternative Schedulers section below.
Step 5: Configure Program.cs
Update your Program.cs to register Semantico services. This is the complete configuration from SampleProject:
using Hangfire;
using Hangfire.PostgreSql;
using Semantico.AI;
using Semantico.Core;
using Semantico.Core.PostgreSql;
using Semantico.UI;
using YourProject.Services;
var builder = WebApplication.CreateBuilder(args);
// 1. Configure Hangfire (job scheduler)
builder.Services.AddHangfire((provider, hangfireConfiguration) => hangfireConfiguration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseFilter(new AutomaticRetryAttribute { Attempts = 0 })
.UsePostgreSqlStorage(
builder.Configuration.GetConnectionString("SemanticoContext"),
new PostgreSqlStorageOptions
{
PrepareSchemaIfNecessary = true,
QueuePollInterval = TimeSpan.FromSeconds(1)
}));
builder.Services.AddHangfireServer();
// 2. SEMANTICO: Add core services and configure database provider
builder.Services.AddSemanticoServices(builder.Configuration, options =>
{
// Required: Register your scheduler implementation
options.AddSemanticoScheduler<SemanticoScheduler>();
// Optional: Base URL for notification links
options.BaseUrl = "https://localhost:7187/semantico";
// Optional: Enable AI features (experimental)
options.UseAI = true;
})
.UsePostgreSql(builder.Configuration.GetConnectionString("SemanticoContext")!, "semantico");
// 3. SEMANTICO: Add UI components
builder.Services.AddSemanticoUI();
// 4. SEMANTICO: Add AI services (optional)
builder.Services.AddSemanticoAI(builder.Configuration);
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles(); // Required: Serves Semantico UI assets
// 5. SEMANTICO: Configure admin UI with authentication
app.UseSemanticoUI()
.UseBasicAuthentication("admin", "admin") // Change these credentials!
.AddBlazorUI("/semantico");
// Optional: Hangfire dashboard
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
IgnoreAntiforgeryToken = true
});
app.Run();
For SQL Server
If using SQL Server instead of PostgreSQL, make these changes:
using Hangfire.SqlServer;
using Semantico.Core.SqlServer;
// Replace PostgreSQL configuration with SQL Server:
builder.Services.AddSemanticoServices(builder.Configuration, options =>
{
options.AddSemanticoScheduler<SemanticoScheduler>();
})
.UseSqlServer(builder.Configuration.GetConnectionString("SemanticoContext")!, "semantico");
// Update Hangfire to use SQL Server:
builder.Services.AddHangfire(config => config
.UseSqlServerStorage(
builder.Configuration.GetConnectionString("SemanticoContext")));
Update connection string in appsettings.json:
{
"ConnectionStrings": {
"SemanticoContext": "Server=localhost;Database=semantico;User Id=sa;Password=YourPassword123!;TrustServerCertificate=True"
}
}
Step 6: Optional - Extended Timeouts for AI Operations
If you plan to use AI features, configure extended timeouts for long-running operations (from SampleProject):
// Configure Kestrel server limits for long-running AI operations
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(5);
serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(5);
});
// Configure Blazor Server with extended timeouts for long-running AI operations
builder.Services.AddServerSideBlazor()
.AddCircuitOptions(options =>
{
options.DisconnectedCircuitMaxRetained = 100;
options.DisconnectedCircuitRetentionPeriod = TimeSpan.FromMinutes(3);
options.JSInteropDefaultCallTimeout = TimeSpan.FromMinutes(5);
options.MaxBufferedUnacknowledgedRenderBatches = 10;
});
// Increase timeout for all HTTP clients (including AI provider APIs)
builder.Services.AddHttpClient().ConfigureHttpClientDefaults(http =>
{
http.ConfigureHttpClient(client =>
{
client.Timeout = TimeSpan.FromMinutes(5);
});
});
Step 7: Run Your Application
dotnet run
On first run, Semantico will automatically create the database schema and apply migrations.
Navigate to:
- Semantico Admin UI: https://localhost:7187/semantico
- Hangfire Dashboard: https://localhost:7187/hangfire (if enabled)
Default credentials (basic auth):
- Username:
admin - Password:
admin
⚠️ Important: Change default credentials in production!
Complete Program.cs Example (Production-Ready)
Here’s the complete Program.cs from SampleProject with all features enabled:
using Hangfire;
using Hangfire.PostgreSql;
using Semantico.AI;
using Semantico.Core;
using Semantico.Core.PostgreSql;
using Semantico.UI;
using YourProject.Services;
var builder = WebApplication.CreateBuilder(args);
// Configure Kestrel server limits for long-running AI operations
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(5);
serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(5);
});
// Increase timeout for all HTTP clients
builder.Services.AddHttpClient().ConfigureHttpClientDefaults(http =>
{
http.ConfigureHttpClient(client =>
{
client.Timeout = TimeSpan.FromMinutes(5);
});
});
// Configure Hangfire
builder.Services.AddHangfire((provider, hangfireConfiguration) => hangfireConfiguration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseFilter(new AutomaticRetryAttribute { Attempts = 0 })
.UsePostgreSqlStorage(
builder.Configuration.GetConnectionString("SemanticoContext"),
new PostgreSqlStorageOptions
{
PrepareSchemaIfNecessary = true,
QueuePollInterval = TimeSpan.FromSeconds(1)
}));
builder.Services.AddHangfireServer();
// SEMANTICO: Add core services and configure database provider
builder.Services.AddSemanticoServices(builder.Configuration, options =>
{
options.AddSemanticoScheduler<SemanticoScheduler>();
options.BaseUrl = "https://localhost:7187/semantico";
options.UseAI = true; // Optional: Enable AI features (experimental)
})
.UsePostgreSql(builder.Configuration.GetConnectionString("SemanticoContext")!, "semantico");
// SEMANTICO: Add UI components
builder.Services.AddSemanticoUI();
// SEMANTICO: Add AI services (optional)
builder.Services.AddSemanticoAI(builder.Configuration);
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles(); // Required: Serves Semantico UI assets
// SEMANTICO: Configure admin UI
app.UseSemanticoUI()
.UseBasicAuthentication("admin", "admin") // Change in production!
.AddBlazorUI("/semantico");
// Optional: Hangfire dashboard
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
IgnoreAntiforgeryToken = true
});
app.Run();
Custom Authorization Provider
Replace basic authentication with your own authorization logic:
using Microsoft.AspNetCore.Http;
using Semantico.UI.AspNet;
public class CustomAuthorizationProvider : ISemanticoAuthorizationProvider
{
public Task<bool> IsAuthorizedAsync(HttpContext context)
{
// Your authorization logic here
// Example: Check if user is authenticated and has specific role
return Task.FromResult(
context.User.Identity?.IsAuthenticated == true &&
context.User.IsInRole("SemanticoAdmin"));
}
}
Register in Program.cs:
builder.Services.AddSemanticoServices(builder.Configuration, options =>
{
options.AddSemanticoScheduler<SemanticoScheduler>();
})
.UsePostgreSql(builder.Configuration.GetConnectionString("SemanticoContext")!, "semantico");
builder.Services.AddSemanticoUI(options =>
{
options.AddAuthorizationProvider<CustomAuthorizationProvider>();
});
// Use custom authorization instead of basic auth
app.UseSemanticoUI()
.UseAuthorization() // Instead of UseBasicAuthentication
.AddBlazorUI("/semantico");
Alternative Schedulers
Using Quartz.NET
using Quartz;
using Semantico.Core.Worker;
public class QuartzSemanticoScheduler : ISemanticoScheduler
{
private readonly ISchedulerFactory _schedulerFactory;
public QuartzSemanticoScheduler(ISchedulerFactory schedulerFactory)
{
_schedulerFactory = schedulerFactory;
}
public async void AddOrUpdate(int subscriptionId, string subscriptionName, string cron)
{
var scheduler = await _schedulerFactory.GetScheduler();
var job = JobBuilder.Create<SemanticoJob>()
.WithIdentity($"semantico-{subscriptionId}")
.UsingJobData("subscriptionId", subscriptionId)
.Build();
var trigger = TriggerBuilder.Create()
.WithIdentity($"semantico-{subscriptionId}-trigger")
.WithCronSchedule(cron)
.Build();
await scheduler.ScheduleJob(job, trigger);
}
public async void Remove(int subscriptionId, string subscriptionName)
{
var scheduler = await _schedulerFactory.GetScheduler();
await scheduler.DeleteJob(new JobKey($"semantico-{subscriptionId}"));
}
}
public class SemanticoJob : IJob
{
private readonly IJobService _jobService;
public SemanticoJob(IJobService jobService)
{
_jobService = jobService;
}
public async Task Execute(IJobExecutionContext context)
{
var subscriptionId = context.JobDetail.JobDataMap.GetInt("subscriptionId");
await _jobService.ExecuteQuery(subscriptionId);
}
}
Troubleshooting
Issue: “Semantico:EncryptionKey must be configured”
Solution: Generate and add encryption key to appsettings.json:
openssl rand -base64 32
Issue: “Cannot create database schema”
Solution: Ensure your database user has CREATE SCHEMA permissions:
PostgreSQL:
GRANT CREATE ON DATABASE semantico TO your_user;
SQL Server:
GRANT CREATE SCHEMA TO your_user;
Issue: Jobs not executing
Solutions:
- Verify Hangfire is configured and running
- Check Hangfire dashboard at
/hangfirefor job status - Ensure
AddHangfireServer()is called - Verify database connection
Issue: UI not loading at /semantico
Solutions:
- Verify route matches
.AddBlazorUI("/semantico") - Check browser console for errors
- Ensure
AddServerSideBlazor()is configured - Try clearing browser cache
Issue: Authentication failing
Solutions:
- Verify credentials match
.UseBasicAuthentication("admin", "admin") - Check if custom authorization provider is properly configured
- Ensure
UseAuthorization()is called before Semantico UI
Issue: AI features not working
Solutions:
- Verify
options.UseAI = trueis set - Check LLM configuration in appsettings.json
- Verify API key is valid and has quota
- Check application logs for API errors
- Ensure extended timeouts are configured (Step 6)
Production Considerations
Security
✅ Change default credentials - Never use admin/admin in production ✅ Use environment variables - Store sensitive config outside appsettings.json ✅ Enable HTTPS - Always use HTTPS in production ✅ Implement proper auth - Use custom authorization provider ✅ Rotate encryption keys - Regularly update encryption keys
Example with environment variables:
{
"Semantico": {
"EncryptionKey": "${SEMANTICO_ENCRYPTION_KEY}",
"LLM": {
"ApiKey": "${LLM_API_KEY}"
}
}
}
Performance
✅ Connection pooling - Configure database connection pooling ✅ Hangfire workers - Adjust worker count based on load ✅ Memory monitoring - Monitor memory usage for large result sets ✅ Query timeouts - Set appropriate execution timeouts
Monitoring
✅ Application logging - Enable detailed logging for troubleshooting ✅ Hangfire dashboard - Monitor job execution and failures ✅ Query alerts - Set up notifications for critical failures ✅ AI usage tracking - Monitor token usage and costs (if using AI)
Next Steps
Now that Semantico is installed:
- Connect your first data source - Add databases to monitor
- Create your first query - Define SQL monitoring queries
- Set up a subscription - Schedule automated execution
- Configure notifications - Send results via Email, Teams, Slack, or Jira
Additional Resources
- 📚 Configuration Guide - Detailed configuration options
- 🚀 Quick Start - 5-minute quickstart guide
- 🎓 Features Overview - Complete feature documentation
- 🐛 Report Issues