mirror of
https://github.com/mxpv/podsync.git
synced 2024-05-11 05:55:04 +00:00
Prepare for production
- Add caddy server - Add Docker - Minor fixes in status endpoint
This commit is contained in:
2
src/Podsync/Caddy.Dockerfile
Normal file
2
src/Podsync/Caddy.Dockerfile
Normal file
@@ -0,0 +1,2 @@
|
||||
FROM zzrot/alpine-caddy
|
||||
COPY Caddyfile /etc/Caddyfile
|
||||
32
src/Podsync/Caddyfile
Normal file
32
src/Podsync/Caddyfile
Normal file
@@ -0,0 +1,32 @@
|
||||
new.podsync.net
|
||||
gzip
|
||||
|
||||
errors stdout
|
||||
|
||||
ratelimit 2 3 second {
|
||||
/feed
|
||||
/download
|
||||
}
|
||||
|
||||
proxy / {%REDIRECT_HOST%}:{%REDIRECT_PORT%} {
|
||||
header_upstream Host {host}
|
||||
transparent
|
||||
}
|
||||
|
||||
tls pavlenko.maksym@gmail.com
|
||||
|
||||
header / {
|
||||
# Remove ASP.NET specific headers
|
||||
-Server
|
||||
-X-Powered-By
|
||||
-X-Sourcefiles
|
||||
|
||||
# Enable cross-site filter (XSS) and tell browser to block detected attacks
|
||||
X-XSS-Protection "1; mode=block"
|
||||
|
||||
# Prevent some browsers from MIME-sniffing a response away from the declared Content-Type
|
||||
X-Content-Type-Options "nosniff"
|
||||
|
||||
# Disallow the site to be rendered within a frame (clickjacking protection)
|
||||
X-Frame-Options "DENY"
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Podsync.Services.Resolver;
|
||||
using Podsync.Services.Storage;
|
||||
@@ -7,6 +8,8 @@ namespace Podsync.Controllers
|
||||
{
|
||||
public class StatusController : Controller
|
||||
{
|
||||
private const string ErrorStatus = "ERROR";
|
||||
|
||||
private readonly IStorageService _storageService;
|
||||
private readonly IResolverService _resolverService;
|
||||
|
||||
@@ -18,11 +21,23 @@ namespace Podsync.Controllers
|
||||
|
||||
public async Task<string> Index()
|
||||
{
|
||||
var time = await _storageService.Ping();
|
||||
var storageStatus = ErrorStatus;
|
||||
|
||||
try
|
||||
{
|
||||
var time = await _storageService.Ping();
|
||||
storageStatus = time.ToString();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
var resolverStatus = _resolverService.Version ?? ErrorStatus;
|
||||
|
||||
return $"Path: {Request.Path}\r\n" +
|
||||
$"Redis: {time}\r\n" +
|
||||
$"Resolve: {_resolverService.Version}";
|
||||
$"Redis: {storageStatus}\r\n" +
|
||||
$"Resolve: {resolverStatus}";
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/Podsync/Deploy.txt
Normal file
14
src/Podsync/Deploy.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
$> ./Up.ps1
|
||||
|
||||
$> docker-machine create --driver digitalocean
|
||||
--digitalocean-accescean-image=ubuntu-16-04-x64
|
||||
--digitalocean-region=ams2
|
||||
--digitalocean-backups=true
|
||||
--digitalocean-size=512mb
|
||||
podsync
|
||||
|
||||
$> docker-machine env podsync
|
||||
|
||||
$> $env:COMPOSE_CONVERT_WINDOWS_PATHS=0
|
||||
|
||||
$> docker-compose up -d
|
||||
16
src/Podsync/Dockerfile
Normal file
16
src/Podsync/Dockerfile
Normal file
@@ -0,0 +1,16 @@
|
||||
FROM microsoft/aspnetcore:1.0.3
|
||||
|
||||
ARG PORT=56247
|
||||
ARG PUBLISH_DIR="bin/Publish"
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENV ASPNETCORE_URLS http://+:$PORT
|
||||
EXPOSE $PORT
|
||||
|
||||
COPY $PUBLISH_DIR .
|
||||
|
||||
# Install Python for youtube-dl
|
||||
RUN apt-get update && apt-get install -y python && chmod a+rx youtube-dl
|
||||
|
||||
ENTRYPOINT ["dotnet", "Podsync.dll"]
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using HashidsNet;
|
||||
using Microsoft.Extensions.Options;
|
||||
@@ -28,31 +30,62 @@ namespace Podsync.Services.Storage
|
||||
|
||||
private static readonly IHashids HashIds = new Hashids(IdSalt, IdLength);
|
||||
|
||||
private readonly IDatabase _db;
|
||||
private readonly string _cs;
|
||||
private IDatabase _db;
|
||||
|
||||
public RedisStorage(IOptions<PodsyncConfiguration> configuration)
|
||||
{
|
||||
var cs = configuration.Value.RedisConnectionString;
|
||||
var connection = ConnectionMultiplexer.ConnectAsync(cs).GetAwaiter().GetResult();
|
||||
_cs = configuration.Value.RedisConnectionString;
|
||||
}
|
||||
|
||||
_db = connection.GetDatabase();
|
||||
private IDatabase Db
|
||||
{
|
||||
get { return LazyInitializer.EnsureInitialized(ref _db, () => Connect(_cs).GetAwaiter().GetResult().GetDatabase()); }
|
||||
}
|
||||
|
||||
private static async Task<ConnectionMultiplexer> Connect(string cs)
|
||||
{
|
||||
var options = ConfigurationOptions.Parse(cs);
|
||||
|
||||
try
|
||||
{
|
||||
return await ConnectionMultiplexer.ConnectAsync(options);
|
||||
}
|
||||
catch (PlatformNotSupportedException)
|
||||
{
|
||||
// Can't connect via address on Linux environments, using workaround
|
||||
// See https://github.com/StackExchange/StackExchange.Redis/issues/410#issuecomment-246332140
|
||||
var addressEndpoint = options.EndPoints.SingleOrDefault() as DnsEndPoint;
|
||||
if (addressEndpoint != null)
|
||||
{
|
||||
var ip = await Dns.GetHostEntryAsync(addressEndpoint.Host);
|
||||
options.EndPoints.Remove(addressEndpoint);
|
||||
options.EndPoints.Add(ip.AddressList.First(), addressEndpoint.Port);
|
||||
}
|
||||
|
||||
return await ConnectionMultiplexer.ConnectAsync(options);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_db.Multiplexer.Dispose();
|
||||
if (_db != null)
|
||||
{
|
||||
_db.Multiplexer.Dispose();
|
||||
_db = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<TimeSpan> Ping()
|
||||
{
|
||||
return _db.PingAsync();
|
||||
return Db.PingAsync();
|
||||
}
|
||||
|
||||
public async Task<string> Save(FeedMetadata metadata)
|
||||
{
|
||||
var id = await MakeId();
|
||||
|
||||
await _db.HashSetAsync(id, new[]
|
||||
await Db.HashSetAsync(id, new[]
|
||||
{
|
||||
new HashEntry(ProviderField, metadata.Provider.ToString()),
|
||||
new HashEntry(TypeField, metadata.LinkType.ToString()),
|
||||
@@ -61,7 +94,7 @@ namespace Podsync.Services.Storage
|
||||
new HashEntry(PageSizeField, metadata.PageSize),
|
||||
});
|
||||
|
||||
await _db.KeyExpireAsync(id, TimeSpan.FromDays(1));
|
||||
await Db.KeyExpireAsync(id, TimeSpan.FromDays(1));
|
||||
|
||||
return id;
|
||||
}
|
||||
@@ -73,10 +106,10 @@ namespace Podsync.Services.Storage
|
||||
throw new ArgumentException("Feed key can't be empty");
|
||||
}
|
||||
|
||||
var entries = await _db.HashGetAllAsync(key);
|
||||
var entries = await Db.HashGetAllAsync(key);
|
||||
|
||||
// Expire after 3 month if no use
|
||||
await _db.KeyExpireAsync(key, TimeSpan.FromDays(90));
|
||||
await Db.KeyExpireAsync(key, TimeSpan.FromDays(90));
|
||||
|
||||
if (entries.Length == 0)
|
||||
{
|
||||
@@ -107,12 +140,12 @@ namespace Podsync.Services.Storage
|
||||
|
||||
public Task ResetCounter()
|
||||
{
|
||||
return _db.KeyDeleteAsync(IdKey);
|
||||
return Db.KeyDeleteAsync(IdKey);
|
||||
}
|
||||
|
||||
public async Task<string> MakeId()
|
||||
{
|
||||
var id = await _db.StringIncrementAsync(IdKey);
|
||||
var id = await Db.StringIncrementAsync(IdKey);
|
||||
return HashIds.EncodeLong(id);
|
||||
}
|
||||
|
||||
|
||||
13
src/Podsync/Up.ps1
Normal file
13
src/Podsync/Up.ps1
Normal file
@@ -0,0 +1,13 @@
|
||||
$OUTPUT_DIR = 'bin/Publish'
|
||||
|
||||
& "dotnet" restore
|
||||
|
||||
Remove-Item $OUTPUT_DIR -Force -Recurse -ErrorAction Ignore
|
||||
|
||||
& "dotnet" publish --configuration release --output $OUTPUT_DIR
|
||||
|
||||
& "docker" build -t podsync .
|
||||
|
||||
# docker run -d -p 5001:5001 podsync
|
||||
|
||||
& "docker-compose" up -d
|
||||
27
src/Podsync/docker-compose.yml
Normal file
27
src/Podsync/docker-compose.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
version: '2'
|
||||
|
||||
services:
|
||||
app:
|
||||
image: podsync
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- PORT=56247
|
||||
environment:
|
||||
- Podsync:RedisConnectionString=redis
|
||||
redis:
|
||||
image: redis
|
||||
command: redis-server --appendonly yes
|
||||
volumes:
|
||||
- /redis_data:/data
|
||||
caddy:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Caddy.Dockerfile
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
environment:
|
||||
- REDIRECT_HOST=app
|
||||
- REDIRECT_PORT=56247
|
||||
@@ -57,7 +57,9 @@
|
||||
"Views",
|
||||
"Areas/**/Views",
|
||||
"appsettings.json",
|
||||
"web.config"
|
||||
"web.config",
|
||||
"Dockerfile",
|
||||
"youtube-dl"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
BIN
src/Podsync/youtube-dl
Normal file
BIN
src/Podsync/youtube-dl
Normal file
Binary file not shown.
Reference in New Issue
Block a user