Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +0,0 @@
[submodule "LDAP/pown"]
path = LDAP/pown
url = https://github.com/anishapant21/pown.sh.git
[submodule "LDAP/LDAPServer"]
path = LDAP/LDAPServer
url = https://github.com/mieweb/LDAPServer.git
35 changes: 32 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,38 @@ RUN apt update && apt -y install git make npm

# Install the software. We include the .git directory so that the software can
# update itself without replacing the entire container.
COPY . /opt/opensource-server
WORKDIR /opt/opensource-server
RUN make install
ARG OPENSOURCE_SERVER_BRANCH=main
RUN git clone \
--branch=${OPENSOURCE_SERVER_BRANCH} \
https://github.com/mieweb/opensource-server.git \
/opt/opensource-server \
&& cd /opt/opensource-server \
&& make install

# Install the ldap-gateway package
ARG LDAP_GATEWAY_BRANCH=main
RUN git clone \
--branch=${LDAP_GATEWAY_BRANCH} \
https://github.com/mieweb/LDAPServer.git \
/opt/ldap-gateway \
&& cd /opt/ldap-gateway \
&& npm install \
&& npm run build \
&& adduser --system --group --disabled-login --no-create-home --home /nonexistent ldap-gateway \
&& chown -R ldap-gateway:ldap-gateway /opt/ldap-gateway \
&& cp /opt/ldap-gateway/nfpm/systemd/ldap-gateway.service /etc/systemd/system/ldap-gateway.service \
&& systemctl enable ldap-gateway

# Tag the exposed ports for services handled by the container
# NGINX (http, https, quic)
EXPOSE 80
EXPOSE 443
EXPOSE 443/udp
# DNSMASQ
EXPOSE 53
EXPOSE 53/udp
# LDAP Gateway
EXPOSE 686

# Configure systemd to run properly in a container. This isn't nessary for LXC
# in Proxmox, but is useful for testing with Docker directly.
Expand Down
1 change: 0 additions & 1 deletion LDAP/LDAPServer
Submodule LDAPServer deleted from 00b8df
1 change: 0 additions & 1 deletion LDAP/README.md

This file was deleted.

1 change: 0 additions & 1 deletion LDAP/pown
Submodule pown deleted from a2a19a
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up (queryInterface, Sequelize) {
// Create HTTPServices table
await queryInterface.createTable('HTTPServices', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
serviceId: {
type: Sequelize.INTEGER,
allowNull: false,
unique: true,
references: {
model: 'Services',
key: 'id'
},
onDelete: 'CASCADE'
},
externalHostname: {
type: Sequelize.STRING(255),
allowNull: false
},
externalDomainId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'ExternalDomains',
key: 'id'
}
},
createdAt: {
type: Sequelize.DATE,
allowNull: false
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false
}
});

// Create TransportServices table
await queryInterface.createTable('TransportServices', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
serviceId: {
type: Sequelize.INTEGER,
allowNull: false,
unique: true,
references: {
model: 'Services',
key: 'id'
},
onDelete: 'CASCADE'
},
protocol: {
type: Sequelize.ENUM('tcp', 'udp'),
allowNull: false
},
externalPort: {
type: Sequelize.INTEGER.UNSIGNED,
allowNull: false
},
tls: {
type: Sequelize.BOOLEAN,
allowNull: true
},
createdAt: {
type: Sequelize.DATE,
allowNull: false
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false
}
});

// Add unique constraint for HTTPServices
await queryInterface.addIndex('HTTPServices', ['externalHostname', 'externalDomainId'], {
unique: true,
name: 'http_services_unique_hostname_domain'
});

// Add unique constraint for TransportServices
await queryInterface.addIndex('TransportServices', ['protocol', 'externalPort'], {
unique: true,
name: 'transport_services_unique_protocol_port'
});

// Migrate existing data from Services to HTTPServices
const servicesTable = queryInterface.quoteIdentifier('Services');
const [services, _] = await queryInterface.sequelize.query(`
SELECT * FROM ${servicesTable}
`);
const httpServices = services.filter(s => s.type === 'http').map(s => ({
serviceId: s.id,
externalHostname: s.externalHostname,
externalDomainId: s.externalDomainId,
createdAt: s.createdAt,
updatedAt: s.updatedAt
}));
// migrate existing data from Services to TransportServices
const transportServices = services.filter(s => s.type === 'tcp' || s.type === 'udp').map(s => ({
serviceId: s.id,
protocol: s.type,
externalPort: s.externalPort,
tls: s.tls,
createdAt: s.createdAt,
updatedAt: s.updatedAt
}));

// Remove old indexes from Services table
await queryInterface.removeIndex('Services', 'services_http_unique_hostname_domain');
await queryInterface.removeIndex('Services', 'services_layer4_unique_port');

// Remove columns from Services table that are now in child tables
await queryInterface.removeColumn('Services', 'externalPort');
await queryInterface.removeColumn('Services', 'tls');
await queryInterface.removeColumn('Services', 'externalHostname');
await queryInterface.removeColumn('Services', 'externalDomainId');

// rename tcp and udp service types to transport
await queryInterface.changeColumn('Services', 'type', {
type: Sequelize.ENUM('http', 'transport', 'tcp', 'udp'),
allowNull: false
});
await queryInterface.bulkUpdate('Services', { type: 'transport' }, { [Sequelize.Op.or]: [ { type: 'tcp' }, { type: 'udp' } ] });
await queryInterface.changeColumn('Services', 'type', {
type: Sequelize.ENUM('http', 'transport'),
allowNull: false
});

// insert migrated data into new tables AFTER schema changes because of how sqlite3 handles cascades
if (httpServices.length > 0)
await queryInterface.bulkInsert('HTTPServices', httpServices);
if (transportServices.length > 0)
await queryInterface.bulkInsert('TransportServices', transportServices);
},

async down (queryInterface, Sequelize) {
// Recreate old indexes on Services table
await queryInterface.addIndex('Services', ['externalHostname', 'externalDomainId'], {
unique: true,
name: 'services_http_unique_hostname_domain',
where: {
type: 'http'
}
});

await queryInterface.addIndex('Services', ['type', 'externalPort'], {
unique: true,
name: 'services_layer4_unique_port'
});

// Add columns back to Services table
await queryInterface.addColumn('Services', 'externalHostname', {
type: Sequelize.STRING(255),
allowNull: true
});

await queryInterface.addColumn('Services', 'externalDomainId', {
type: Sequelize.INTEGER,
allowNull: true,
references: {
model: 'ExternalDomains',
key: 'id'
}
});

await queryInterface.addColumn('Services', 'tls', {
type: Sequelize.BOOLEAN,
allowNull: true
});

await queryInterface.addColumn('Services', 'externalPort', {
type: Sequelize.INTEGER.UNSIGNED,
allowNull: true
});

// Change type enum back to include tcp and udp
await queryInterface.changeColumn('Services', 'type', {
type: Sequelize.ENUM('http', 'transport', 'tcp', 'udp'),
allowNull: false
});

// Migrate data back from child tables
const servicesTable = queryInterface.quoteIdentifier('Services');
const httpServicesTable = queryInterface.quoteIdentifier('HTTPServices');
const transportServicesTable = queryInterface.quoteIdentifier('TransportServices');

// Restore HTTP service data
const [httpServices, _] = await queryInterface.sequelize.query(`
SELECT * FROM ${httpServicesTable}
`);
for (const hs of httpServices) {
await queryInterface.bulkUpdate('Services', {
externalHostname: hs.externalHostname,
externalDomainId: hs.externalDomainId
}, { id: hs.serviceId });
}

// Restore transport service data and convert type back to tcp/udp
const [transportServices, __] = await queryInterface.sequelize.query(`
SELECT * FROM ${transportServicesTable}
`);
for (const ts of transportServices) {
await queryInterface.bulkUpdate('Services', {
type: ts.protocol,
externalPort: ts.externalPort,
tls: ts.tls
}, { id: ts.serviceId });
}

// Remove transport from enum, leaving only http, tcp, udp
await queryInterface.changeColumn('Services', 'type', {
type: Sequelize.ENUM('http', 'tcp', 'udp'),
allowNull: false
});

// Drop child tables
await queryInterface.dropTable('TransportServices');
await queryInterface.dropTable('HTTPServices');
}
};
59 changes: 59 additions & 0 deletions create-a-container/migrations/20251202201123-add-dns-services.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up (queryInterface, Sequelize) {
// Add 'dns' to Service type enum
await queryInterface.changeColumn('Services', 'type', {
type: Sequelize.ENUM('http', 'transport', 'dns'),
allowNull: false
});

// Create DnsServices table
await queryInterface.createTable('DnsServices', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
serviceId: {
type: Sequelize.INTEGER,
allowNull: false,
unique: true,
references: {
model: 'Services',
key: 'id'
},
onDelete: 'CASCADE'
},
recordType: {
type: Sequelize.ENUM('SRV'),
allowNull: false,
defaultValue: 'SRV'
},
dnsName: {
type: Sequelize.STRING(255),
allowNull: false
},
createdAt: {
type: Sequelize.DATE,
allowNull: false
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false
}
});
},

async down (queryInterface, Sequelize) {
// Drop DnsServices table
await queryInterface.dropTable('DnsServices');

// Remove 'dns' from Service type enum
await queryInterface.changeColumn('Services', 'type', {
type: Sequelize.ENUM('http', 'transport'),
allowNull: false
});
}
};
39 changes: 39 additions & 0 deletions create-a-container/models/dns-service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"use strict";
const { Model } = require('sequelize');

module.exports = (sequelize, DataTypes) => {
class DnsService extends Model {
static associate(models) {
DnsService.belongsTo(models.Service, { foreignKey: 'serviceId', as: 'service' });
}
}

DnsService.init({
serviceId: {
type: DataTypes.INTEGER,
allowNull: false,
unique: true,
references: {
model: 'Services',
key: 'id'
}
},
recordType: {
type: DataTypes.ENUM('SRV'),
allowNull: false,
defaultValue: 'SRV'
},
dnsName: {
type: DataTypes.STRING(255),
allowNull: false,
validate: {
notEmpty: true
}
}
}, {
sequelize,
modelName: 'DnsService'
});

return DnsService;
};
Loading
Loading